From patchwork Tue Mar 15 20:04:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Sementsov-Ogievskiy X-Patchwork-Id: 8592281 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A63B0C0553 for ; Tue, 15 Mar 2016 20:14:50 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BCCD82026C for ; Tue, 15 Mar 2016 20:14:49 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A11372014A for ; Tue, 15 Mar 2016 20:14:48 +0000 (UTC) Received: from localhost ([::1]:51257 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1afvMd-00025s-TY for patchwork-qemu-devel@patchwork.kernel.org; Tue, 15 Mar 2016 16:14:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38967) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1afvDr-0008Px-ND for qemu-devel@nongnu.org; Tue, 15 Mar 2016 16:05:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1afvDq-0008Lr-6R for qemu-devel@nongnu.org; Tue, 15 Mar 2016 16:05:43 -0400 Received: from mailhub.sw.ru ([195.214.232.25]:1043 helo=relay.sw.ru) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1afvDp-0008KE-I2 for qemu-devel@nongnu.org; Tue, 15 Mar 2016 16:05:42 -0400 Received: from kvm.sw.ru. ([10.28.8.145]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id u2FK4bCq005992; Tue, 15 Mar 2016 23:05:21 +0300 (MSK) From: Vladimir Sementsov-Ogievskiy To: qemu-devel@nongnu.org Date: Tue, 15 Mar 2016 23:04:22 +0300 Message-Id: <1458072268-53705-17-git-send-email-vsementsov@virtuozzo.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1458072268-53705-1-git-send-email-vsementsov@virtuozzo.com> References: <1458072268-53705-1-git-send-email-vsementsov@virtuozzo.com> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x X-Received-From: 195.214.232.25 Cc: kwolf@redhat.com, vsementsov@virtuozzo.com, famz@redhat.com, qemu-block@nongnu.org, mreitz@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, den@openvz.org, jsnow@redhat.com Subject: [Qemu-devel] [PATCH 16/22] qemu: command line option for dirty bitmaps 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The patch adds the following command line option: -dirty-bitmap [option1=val1][,option2=val2]... Avaliable options are: name The name of the bitmap. Should be unique per 'file'/'node' and per 'for_node'. node The node to load and bind the bitmap. It should be specified as 'id' suboption of one of '-node' options. granularity Granularity (in bytes) for created dirty bitmap. If the bitmap is already exists in specified 'file'/'file_id'/device it's granularity will not be changed but only checked (an error will be generated if this check fails). enabled on|off Enabled flag for the bitmap. By default the bitmap will be enabled. create on|off By default is off. If on, then new bitmap will be created in the image, if the bitmap with same name is already exists an error will be generated. If off, then the bitmap will be loaded from the image, if there is no one an error will be generated. If create=off and granularity is specified then granularity will be checked for loaded bitmap and if not match an error will be generated. Signed-off-by: Vladimir Sementsov-Ogievskiy --- blockdev.c | 36 +++++++++++++++++++++ include/sysemu/blockdev.h | 1 + include/sysemu/sysemu.h | 1 + qemu-options.hx | 35 +++++++++++++++++++++ vl.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+) diff --git a/blockdev.c b/blockdev.c index 322ca03..3a3d71c 100644 --- a/blockdev.c +++ b/blockdev.c @@ -185,6 +185,12 @@ QemuOpts *drive_def(const char *optstr) return qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false); } +QemuOpts *dirty_bitmap_def(const char *optstr) +{ + return qemu_opts_parse_noisily(qemu_find_opts("dirty-bitmap"), optstr, + false); +} + QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, const char *optstr) { @@ -4084,6 +4090,36 @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp) return head; } +QemuOptsList qemu_dirty_bitmap_opts = { + .name = "dirty-bitmap", + .head = QTAILQ_HEAD_INITIALIZER(qemu_dirty_bitmap_opts.head), + .desc = { + { + .name = "name", + .type = QEMU_OPT_STRING, + .help = "Name of the dirty bitmap", + },{ + .name = "node", + .type = QEMU_OPT_STRING, + .help = "node name to bind the bitmap to (and load it from it)", + },{ + .name = "granularity", + .type = QEMU_OPT_NUMBER, + .help = "granularity", + },{ + .name = "enabled", + .type = QEMU_OPT_BOOL, + .help = "enabled flag (default is 'on')", + },{ + .name = "create", + .type = QEMU_OPT_BOOL, + .help = "create flag (default is 'off'), " + "if on, new dirty bitmap will be created, " + "else the existing one will be loaded" + } + } +}; + QemuOptsList qemu_common_drive_opts = { .name = "drive", .head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head), diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 16432f3..105d11b 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -56,6 +56,7 @@ int drive_get_max_devs(BlockInterfaceType type); DriveInfo *drive_get_next(BlockInterfaceType type); QemuOpts *drive_def(const char *optstr); +QemuOpts *dirty_bitmap_def(const char *optstr); QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, const char *optstr); DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 3bb8897..7dc3980 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -248,6 +248,7 @@ bool usb_enabled(void); extern QemuOptsList qemu_legacy_drive_opts; extern QemuOptsList qemu_common_drive_opts; +extern QemuOptsList qemu_dirty_bitmap_opts; extern QemuOptsList qemu_drive_opts; extern QemuOptsList qemu_chardev_opts; extern QemuOptsList qemu_device_opts; diff --git a/qemu-options.hx b/qemu-options.hx index 0cf7bb9..e750ebc 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -680,6 +680,41 @@ qemu-system-i386 -hda a -hdb b @end example ETEXI +DEF("dirty-bitmap", HAS_ARG, QEMU_OPTION_dirty_bitmap, + "-dirty-bitmap name=name,node=@var{id}\n" + " [,granularity=granularity][,enabled=on|off][,create=on|off]\n", + QEMU_ARCH_ALL) +STEXI +@item -dirty-bitmap @var{option}[,@var{option}[,@var{option}[,...]]] +@findex -dirty-bitmap + +Define a dirty-bitmap. Valid options are: + +@table @option +@item name=@var{name} +The name of the bitmap. Should be unique per @var{file}/@var{node} and per +@var{for_node}. +@item node=@var{node} +The node to load and bind the bitmap. It should be specified as @var{id} suboption +of one of @option{-node} options. +@item granularity=@var{granularity} +Granularity (in bytes) for created dirty bitmap. If the bitmap is already +exists in specified @var{file}/@var{file_id}/@var{device} it's granularity will +not be changed but only checked (an error will be generated if this check +fails). +@item enabled=@var{enabled} +Enabled flag for the bitmap. By default the bitmap will be enabled. +@item create=@var{create} +By default is off. +If on, then new bitmap will be created in the image, if the bitmap with same +name is already exists an error will be generated. +If off, then the bitmap will be loaded from the image, if there is no one an +error will be generated. +If create=off and granularity is specified then granularity will be checked for +loaded bitmap and if not match an error will be generated. +@end table +ETEXI + DEF("mtdblock", HAS_ARG, QEMU_OPTION_mtdblock, "-mtdblock file use 'file' as on-board Flash memory image\n", QEMU_ARCH_ALL) diff --git a/vl.c b/vl.c index 7a28982..31f5cdf 100644 --- a/vl.c +++ b/vl.c @@ -1155,6 +1155,74 @@ static int cleanup_add_fd(void *opaque, QemuOpts *opts, Error **errp) #define MTD_OPTS "" #define SD_OPTS "" +static int dirty_bitmap_func(void *opaque, QemuOpts *opts, Error **errp_unused) +{ + Error *local_err = NULL; + BlockDriverState *bs = NULL; + BdrvDirtyBitmap *bitmap = NULL; + + const char *name = qemu_opt_get(opts, "name"); + const char *node = qemu_opt_get(opts, "node"); + + uint64_t granularity = qemu_opt_get_number(opts, "granularity", 0); + bool enabled = qemu_opt_get_bool(opts, "enabled", true); + bool create = qemu_opt_get_bool(opts, "create", false); + + if (name == NULL) { + error_report("'name' option is necessary"); + return -1; + } + + if (node == NULL) { + error_report("'node' option is necessary"); + return -1; + } + + bs = bdrv_lookup_bs(node, node, &local_err); + if (bs == NULL) { + error_report_err(local_err); + return -1; + } + + if (create) { + if (bdrv_load_check_dirty_bitmap(bs, name)) { + error_report("bitmap '%s' already exists", name); + return -1; + } + + if (granularity == 0) { + granularity = bdrv_get_default_bitmap_granularity(bs); + } + + bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, &local_err); + if (bitmap == NULL) { + error_report_err(local_err); + return -1; + } + } else { + bitmap = bdrv_load_dirty_bitmap(bs, name, &local_err); + if (bitmap == NULL) { + error_report_err(local_err); + return -1; + } + + if (granularity != 0 && + granularity != bdrv_dirty_bitmap_granularity(bitmap)) { + bdrv_release_dirty_bitmap(bs, bitmap); + error_report("granularity doesn't match"); + return -1; + } + } + + bdrv_dirty_bitmap_set_internal_persistance(bitmap, true); + + if (!enabled) { + bdrv_disable_dirty_bitmap(bitmap); + } + + return 0; +} + static int drive_init_func(void *opaque, QemuOpts *opts, Error **errp) { BlockInterfaceType *block_default_type = opaque; @@ -2994,6 +3062,7 @@ int main(int argc, char **argv, char **envp) module_call_init(MODULE_INIT_QOM); qemu_add_opts(&qemu_drive_opts); + qemu_add_opts(&qemu_dirty_bitmap_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); qemu_add_drive_opts(&qemu_common_drive_opts); qemu_add_drive_opts(&qemu_drive_opts); @@ -3126,6 +3195,11 @@ int main(int argc, char **argv, char **envp) exit(1); } break; + case QEMU_OPTION_dirty_bitmap: + if (dirty_bitmap_def(optarg) == NULL) { + exit(1); + } + break; case QEMU_OPTION_set: if (qemu_set_option(optarg) != 0) exit(1); @@ -4456,6 +4530,11 @@ int main(int argc, char **argv, char **envp) parse_numa_opts(machine_class); + if (qemu_opts_foreach(qemu_find_opts("dirty-bitmap"), + dirty_bitmap_func, NULL, NULL)) { + exit(1); + } + if (qemu_opts_foreach(qemu_find_opts("mon"), mon_init_func, NULL, NULL)) { exit(1);