diff -r -u qemu-kvm-0.12.3+noroms/qemu-monitor.hx qemu-kvm-0.12.3+noroms-patched/qemu-monitor.hx --- qemu-kvm-0.12.3+noroms/qemu-monitor.hx 2010-02-26 03:34:00.000000000 +0100 +++ qemu-kvm-0.12.3+noroms-patched/qemu-monitor.hx 2010-06-14 13:38:01.944659044 +0200 @@ -228,6 +228,23 @@ ETEXI { + .name = "snapshot_create", + .args_type = "name:s?,device:B?", + .params = "[tag|id] [device]", + .help = "create a disk snapshot", + .user_print = monitor_user_noop, + .mhandler.cmd = do_snapshot_create, + }, + +STEXI +@item snapshot_create [@var{tag}|@var{id}] +Create a snapshot of the disk. If @var{tag} is +provided, it is used as human readable identifier. If there is already +a snapshot with the same tag or ID, it is replaced. More info at +@ref{vm_snapshots}. +ETEXI + + { .name = "savevm", .args_type = "name:s?", .params = "[tag|id]", diff -r -u qemu-kvm-0.12.3+noroms/savevm.c qemu-kvm-0.12.3+noroms-patched/savevm.c --- qemu-kvm-0.12.3+noroms/savevm.c 2010-02-26 03:34:00.000000000 +0100 +++ qemu-kvm-0.12.3+noroms-patched/savevm.c 2010-06-14 15:20:10.424032971 +0200 @@ -1757,6 +1757,105 @@ vm_start(); } +/* + * XXX The following functions are factored out from the + * 'do_savevm()'. + * When the addition of the 'snapshot_create()' function + * is accepted - also the 'do_savevm()' should be changed + * to use those (common) funtionality. + */ +static void dsc_sn_name(Monitor * mon, QEMUSnapshotInfo * const sn, + char const * const name) +{ + BlockDriverState * bs; + + bs = get_bs_snapshots(); + if (!bs) { + monitor_printf(mon, "No block device can accept snapshots\n"); + return; + } + + if (name) { + QEMUSnapshotInfo old_sn1, *old_sn = &old_sn1; + int const 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); + } + } +} + +static void dsc_fill_time(QEMUSnapshotInfo * const sn) +{ + /* fill auxiliary fields */ +#ifdef _WIN32 + struct _timeb tb; + _ftime(&tb); + sn->date_sec = tb.time; + sn->date_nsec = tb.millitm * 1000000; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + sn->date_sec = tv.tv_sec; + sn->date_nsec = tv.tv_usec * 1000; +#endif + sn->vm_clock_nsec = qemu_get_clock(vm_clock); +} + +static void dsc_snapshot_create(Monitor * mon, QEMUSnapshotInfo * const sn, + char const * const device) +{ + DriveInfo *dinfo; + BlockDriverState *bs1; + + QTAILQ_FOREACH(dinfo, &drives, next) { + bs1 = dinfo->bdrv; + if (bdrv_has_snapshot(bs1)) { + int ret; + /* There is no VM image. */ + sn->vm_state_size = 0; + if(device && strcmp(device, bdrv_get_device_name(bs1))) + continue; + ret = bdrv_snapshot_create(bs1, sn); + if (ret < 0) { + monitor_printf(mon, "Error while creating snapshot on '%s'\n", + bdrv_get_device_name(bs1)); + } + } + } +} + +/* + * If name is given, create snapshot only for this disk. + * If name is not given, create snapshots for all disks. + */ +void do_snapshot_create(Monitor *mon, const QDict *qdict) +{ + char const * const name = qdict_get_try_str(qdict, "name"); + char const * const device = qdict_get_try_str(qdict, "device"); + QEMUSnapshotInfo sn1, *sn = &sn1; + + /* ??? Should this occur after vm_stop? */ + /* +af+ I really do not know what happens here. */ + qemu_aio_flush(); + + /* Clear the snapshot info */ + memset(sn, 0, sizeof(*sn)); + + dsc_sn_name(mon, sn, name); + dsc_fill_time(sn); + + /* Delete old snapshots of the same name */ + if (name && del_existing_snapshots(mon, name) < 0) { + monitor_printf(mon, "Error while deleting existing snapshot"); + return; + } + + dsc_snapshot_create(mon, sn, device); +} + int load_vmstate(Monitor *mon, const char *name) { DriveInfo *dinfo; diff -r -u qemu-kvm-0.12.3+noroms/sysemu.h qemu-kvm-0.12.3+noroms-patched/sysemu.h --- qemu-kvm-0.12.3+noroms/sysemu.h 2010-02-26 03:34:00.000000000 +0100 +++ qemu-kvm-0.12.3+noroms-patched/sysemu.h 2010-06-14 11:26:58.724033197 +0200 @@ -55,6 +55,7 @@ void qemu_system_reset(void); void do_savevm(Monitor *mon, const QDict *qdict); +void do_snapshot_create(Monitor *mon, const QDict *qdict); int load_vmstate(Monitor *mon, const char *name); void do_delvm(Monitor *mon, const QDict *qdict); void do_info_snapshots(Monitor *mon);