From patchwork Wed Jul 28 19:30:24 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miguel Di Ciurcio Filho X-Patchwork-Id: 60173 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id CC5F2B6F04 for ; Thu, 29 Jul 2010 05:37:02 +1000 (EST) Received: from localhost ([127.0.0.1]:33458 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OeCR1-0005Xt-IR for incoming@patchwork.ozlabs.org; Wed, 28 Jul 2010 15:36:59 -0400 Received: from [140.186.70.92] (port=56867 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OeCMd-0002kq-VE for qemu-devel@nongnu.org; Wed, 28 Jul 2010 15:32:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OeCJM-00046m-Jb for qemu-devel@nongnu.org; Wed, 28 Jul 2010 15:29:05 -0400 Received: from mail-gx0-f173.google.com ([209.85.161.173]:51804) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OeCJM-00046e-GP for qemu-devel@nongnu.org; Wed, 28 Jul 2010 15:29:04 -0400 Received: by gxk19 with SMTP id 19so2068956gxk.4 for ; Wed, 28 Jul 2010 12:29:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references; bh=xe9+N9gSweZNQNI/TvCTMfhTFbKF3Fz8V6YBtAE5mK4=; b=D0guiyfOxE6lxU6OI7znOkGvBvlgwziRu6n0dS4aW/mqOrpLZNAqHlO0B+LoVY2U1x ZEdlt9yZvF6pIILNISYRkYNYiHVIzYtAgjMIOiBWl48tZsnMsmRMnJSeNgI+RUL3KTl2 aSIw5xFQ4bUlqpE78SmTJGZp/g13tZd4mr1t0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=ueCcL55yCcarHwOUBDga2PBzkCJAsKNcwZ0EWOE6cHDFh3KPyC2l99ynub0r91nlzK XhYjM5I06Vk6lizyFzRpkg236Zb+eoItp1vD3RCvsQKc/oFD+DJ157gX6O/KVPlPyOr7 ySRvW78eY/qmawvlnErjf50BjqZrCH/C1Ja6A= Received: by 10.150.52.11 with SMTP id z11mr5186689ybz.149.1280345343566; Wed, 28 Jul 2010 12:29:03 -0700 (PDT) Received: from localhost.localdomain (quake.ic.unicamp.br [143.106.7.51]) by mx.google.com with ESMTPS id u41sm8628909yba.10.2010.07.28.12.28.54 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 28 Jul 2010 12:28:57 -0700 (PDT) From: Miguel Di Ciurcio Filho To: qemu-devel@nongnu.org Date: Wed, 28 Jul 2010 16:30:24 -0300 Message-Id: <1280345424-12918-4-git-send-email-miguel.filho@gmail.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1280345424-12918-1-git-send-email-miguel.filho@gmail.com> References: <1280345424-12918-1-git-send-email-miguel.filho@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: kwolf@redhat.com, Miguel Di Ciurcio Filho , armbru@redhat.com, lcapitulino@redhat.com Subject: [Qemu-devel] [PATCH 3/3] savevm: prevent snapshot overwriting and generate a default name X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch address two issues. 1) When savevm is run using an previously saved snapshot id or name, it will delete the original and create a new one, using the same id and name and not prompting the user of what just happened. This behaviour is not good, IMHO. We add a '-f' parameter to savevm, to really force that to happen, in case the user really wants to. New behavior: (qemu) savevm snap1 An snapshot named 'snap1' already exists (qemu) savevm -f snap1 We do better error reporting in case '-f' is used too than before. 2) When savevm is run without a name or id, the name stays blank. This is a first step to hide the internal id, because I don't see a reason to expose this kind of internals to the user. The new behavior is when savevm is run without parameters a name will be created automaticaly, so the snapshot is accessible to the user without needing the id when loadvm is run. (qemu) savevm (qemu) info snapshots ID TAG VM SIZE DATE VM CLOCK 1 vm-20100728134640 978K 2010-07-28 13:46:40 00:00:08.603 We use a name with the format 'vm-YYYYMMDDHHMMSS'. TODO: I have no clue on how to create a timestamp string when using Windows. Signed-off-by: Miguel Di Ciurcio Filho --- qemu-monitor.hx | 9 ++++--- savevm.c | 59 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 9c27b31..94e8178 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -275,14 +275,15 @@ ETEXI { .name = "savevm", - .args_type = "name:s?", - .params = "[tag|id]", - .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created", + .args_type = "force:-f,name:s?", + .params = "[-f] [name]", + .help = "save a VM snapshot. If no name is provided, a new one will be generated" + "\n\t\t\t -f to overwrite an snapshot if it already exists", .mhandler.cmd = do_savevm, }, STEXI -@item savevm [@var{tag}|@var{id}] +@item savevm [-f] [@var{tag}] @findex savevm Create a snapshot of the whole virtual machine. If @var{tag} is provided, it is used as human readable identifier. If there is already diff --git a/savevm.c b/savevm.c index fb38e8a..ae6f29f 100644 --- a/savevm.c +++ b/savevm.c @@ -1785,7 +1785,7 @@ static int del_existing_snapshots(Monitor *mon, const char *name) void do_savevm(Monitor *mon, const QDict *qdict) { - BlockDriverState *bs, *bs1; + BlockDriverState *bs_vm_state, *bs; QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1; int ret; QEMUFile *f; @@ -1796,7 +1796,9 @@ void do_savevm(Monitor *mon, const QDict *qdict) #else struct timeval tv; #endif + struct tm tm; const char *name = qdict_get_try_str(qdict, "name"); + int force = qdict_get_try_bool(qdict, "force", 0); /* Verify if there is a device that doesn't support snapshots and is writable */ bs = NULL; @@ -1813,8 +1815,8 @@ void do_savevm(Monitor *mon, const QDict *qdict) } } - bs = bdrv_snapshots(); - if (!bs) { + bs_vm_state = bdrv_snapshots(); + if (!bs_vm_state) { monitor_printf(mon, "No block device can accept snapshots\n"); return; } @@ -1825,15 +1827,6 @@ void do_savevm(Monitor *mon, const QDict *qdict) vm_stop(0); memset(sn, 0, sizeof(*sn)); - if (name) { - ret = bdrv_snapshot_find(bs, old_sn, name); - if (ret >= 0) { - pstrcpy(sn->name, sizeof(sn->name), old_sn->name); - pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str); - } else { - pstrcpy(sn->name, sizeof(sn->name), name); - } - } /* fill auxiliary fields */ #ifdef _WIN32 @@ -1847,13 +1840,31 @@ void do_savevm(Monitor *mon, const QDict *qdict) #endif sn->vm_clock_nsec = qemu_get_clock(vm_clock); - /* Delete old snapshots of the same name */ - if (name && del_existing_snapshots(mon, name) < 0) { - goto the_end; + if (name) { + ret = bdrv_snapshot_find(bs_vm_state, old_sn, name); + if (ret == 0) { + if (force) { + ret = del_existing_snapshots(mon, name); + if (ret < 0) { + monitor_printf(mon, "Error deleting snapshot '%s', error: %d\n", + name, ret); + goto the_end; + } + } else { + monitor_printf(mon, "An snapshot named '%s' already exists\n", name); + goto the_end; + } + } + + pstrcpy(sn->name, sizeof(sn->name), name); + } else { + /* TODO: handle Windows */ + localtime_r(&tv.tv_sec, &tm); + strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm); } /* save the VM state */ - f = qemu_fopen_bdrv(bs, 1); + f = qemu_fopen_bdrv(bs_vm_state, 1); if (!f) { monitor_printf(mon, "Could not open VM state file\n"); goto the_end; @@ -1867,23 +1878,23 @@ void do_savevm(Monitor *mon, const QDict *qdict) } /* create the snapshots */ - - bs1 = NULL; - while ((bs1 = bdrv_next(bs1))) { - if (bdrv_can_snapshot(bs1)) { + bs = NULL; + while ((bs = bdrv_next(bs))) { + if (bdrv_can_snapshot(bs)) { /* Write VM state size only to the image that contains the state */ - sn->vm_state_size = (bs == bs1 ? vm_state_size : 0); - ret = bdrv_snapshot_create(bs1, sn); + sn->vm_state_size = (bs_vm_state == bs ? vm_state_size : 0); + ret = bdrv_snapshot_create(bs, sn); if (ret < 0) { monitor_printf(mon, "Error while creating snapshot on '%s'\n", - bdrv_get_device_name(bs1)); + bdrv_get_device_name(bs)); } } } the_end: - if (saved_vm_running) + if (saved_vm_running) { vm_start(); + } } int load_vmstate(const char *name)