qapi: Convert savevm, loadvm, delvm and info snapshots
cover qapi: Convert savevm, loadvm, delvm and info snapshots
This patch series convert these commands into qapi and intruduce QMP commands vm-snapshot-save, vm-snapshot-load, vm-snapshot-delete and query-vm-snapshots. It also rewrite error report for function used by these commands.
Last two patches introduce new functionality of savevm and vm-snapshot-save that you cannot override existing snapshot witouth using 'force' parameter and for QMP you have to always provide name parameter.
Pavel Hrdina (18):
qerror: introduce QERR_GENERIC_ERROR
block: add error parameter to bdrv_snapshot_create() and related
functions
block: add error parameter to bdrv_snapshot_goto() and related
functions
block: add error parameter to bdrv_snapshot_delete() and related
functions
block: add error parameter to bdrv_snapshot_list() and related
functions
block: add error parameter to bdrv_snapshot_find()
block: add error parameter to del_existing_snapshots()
savevm: add error parameter to qemu_savevm_state_begin()
savevm: add error parameter to qemu_savevm_state_iterate()
savevm: add error parameter to qemu_savevm_state_complete()
savevm: add error parameter to qemu_savevm_state()
savevm: add error parameter to qemu_loadvm_state()
qapi: Convert savevm
qapi: Convert loadvm
qapi: Convert delvm
qapi: Convert info snapshots
hmp: allow "bool" parameter to be optional
vm-snapshot-save: add force parameter
block.c | 102 +++++++++++------ block.h | 13 ++- block/qcow2-snapshot.c | 33 +++++- block/qcow2.h | 16 ++- block/rbd.c | 36 ++++-- block/sheepdog.c | 48 +++++--- block_int.h | 13 ++- hmp-commands.hx | 20 ++-- hmp.c | 86 ++++++++++++++ hmp.h | 4 + migration.c | 8 +- monitor.c | 17 +-- qapi-schema.json | 84 ++++++++++++++ qemu-img.c | 8 +- qerror.h | 3 + qmp-commands.hx | 110 ++++++++++++++++++ savevm.c | 301 +++++++++++++++++++++++++------------------------ sysemu.h | 17 ++- vl.c | 7 +- 19 files changed, 659 insertions(+), 267 deletions(-)
Signature · 1 line
1.7.11.2
PATCH 1/18 qerror: introduce QERR_GENERIC_ERROR
--- qerror.h | 3 +++ 1 file changed, 3 insertions(+)
qerror.h +3 -0
@@ -120,6 +120,9 @@ void assert_no_error(Error *err);#define QERR_FEATURE_DISABLED \ ERROR_CLASS_GENERIC_ERROR, "The feature '%s' is not enabled" +#define QERR_GENERIC_ERROR \ + ERROR_CLASS_GENERIC_ERROR, "An (Errno %d) error has occurred" +#define QERR_INVALID_BLOCK_FORMAT \ ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'"
Signature · 1 line
1.7.11.2
Re: [Qemu-devel] [PATCH 01/18] qerror: introduce QERR_GENERIC_ERROR
Quoted 10 lines · On Wed, 15 Aug 2012 09:41:42 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- qerror.h | 3 +++ 1 file changed, 3 insertions(+)qerror.h +0
-0
qerror.h void assert_no_error(Error *err); · line 125
Quoted 6 lines
qerror.h +3
-0@@ -120,6 +120,9 @@ void assert_no_error(Error *err);#define QERR_FEATURE_DISABLED \ ERROR_CLASS_GENERIC_ERROR, "The feature '%s' is not enabled" +#define QERR_GENERIC_ERROR \ + ERROR_CLASS_GENERIC_ERROR, "An (Errno %d) error has occurred" +
You should use error_setg() instead:
http://lists.gnu.org/archive/html/qemu-devel/2012-08/msg04980.html
There usage examples in the series introducing it. It would be better to wait for it to be merged before you use it though, as it's always possible for people to ask for changes.
Quoted 3 lines
qerror.h +0
-0#define QERR_INVALID_BLOCK_FORMAT \ ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'"
Re: [Qemu-devel] [PATCH 01/18] qerror: introduce QERR_GENERIC_ERROR
Quoted 16 lines · Luiz Capitulino
Quoted 13 lines · On Wed, 15 Aug 2012 09:41:42 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- qerror.h | 3 +++ 1 file changed, 3 insertions(+)qerror.h +0
-0@@ -120,6 +120,9 @@ void assert_no_error(Error *err);#define QERR_FEATURE_DISABLED \ ERROR_CLASS_GENERIC_ERROR, "The feature '%s' is not enabled"
Quoted 4 lines
qerror.h void assert_no_error(Error *err); · line 125
Quoted 3 lines
qerror.h +3
-0+#define QERR_GENERIC_ERROR \ + ERROR_CLASS_GENERIC_ERROR, "An (Errno %d) error has occurred" +You should use
error_setg()instead:
I'll fix it for whole patch-series.
Quoted 10 lines
http://lists.gnu.org/archive/html/qemu-devel/2012-08/msg04980.html
There usage examples in the series introducing it. It would be better to wait for it to be merged before you use it though, as it's always possible for people to ask for changes.
Quoted 3 lines
qerror.h +0
-0#define QERR_INVALID_BLOCK_FORMAT \ ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'"
PATCH 2/18 block: add error parameter to bdrv_snapshot_create() and related functions
In reply to Pavel Hrdina--- block.c | 25 +++++++++++++++++-------- block.h | 3 ++- block/qcow2-snapshot.c | 9 ++++++++- block/qcow2.h | 4 +++- block/rbd.c | 20 ++++++++++++++------ block/sheepdog.c | 17 +++++++++-------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 57 insertions(+), 28 deletions(-)
block.c +17 -8
@@ -2661,16 +2661,25 @@ BlockDriverState *bdrv_snapshots(void) }int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv) -return -ENOMEDIUM ; -if (drv->bdrv_snapshot_create) -return drv->bdrv_snapshot_create (bs, sn_info); -if (bs->file) -return bdrv_snapshot_create (bs->file, sn_info); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs)); + ret = -ENOMEDIUM ; + }else if (drv->bdrv_snapshot_create) { + ret = drv->bdrv_snapshot_create (bs, sn_info, errp); + }else if (bs->file) { + ret =bdrv_snapshot_create (bs->file, sn_info, errp); + }else { +error_set (errp,QERR_NOT_SUPPORTED ); + ret = -ENOTSUP ; + } + +return ret; } int bdrv_snapshot_goto(BlockDriverState *bs,
block.h +2 -1
@@ -296,7 +296,8 @@ int bdrv_can_snapshot(BlockDriverState *bs);int bdrv_is_snapshot (BlockDriverState *bs);BlockDriverState *bdrv_snapshots (void );int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info); +QEMUSnapshotInfo *sn_info, +Error **errp);int bdrv_snapshot_goto (BlockDriverState *bs,const char *snapshot_id);int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);
block/qcow2-snapshot.c +8 -1
@@ -25,6 +25,7 @@#include "qemu-common.h" #include "block_int.h" #include "block/qcow2.h" +#include "qerror.h" typedef struct QEMU_PACKED QCowSnapshotHeader {/* header is 8 byte aligned */
@@ -312,7 +313,9 @@ static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name) }/* if no id is provided, a new one is constructed */ -int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info) +int qcow2_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVQcowState *s = bs->opaque;QCowSnapshot *new_snapshot_list =NULL ;
@@ -331,6 +334,8 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)/* Check that the ID is unique */ if (find_snapshot_by_id (bs, sn_info->id_str) >=0 ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"non-existing id identifier" );return -EEXIST ; }
@@ -415,6 +420,8 @@ fail:g_free (sn->name);g_free (l1_table); +error_set (errp,QERR_GENERIC_ERROR , ret); +return ret; }
block/qcow2.h +3 -1
@@ -308,7 +308,9 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,int qcow2_zero_clusters (BlockDriverState *bs,uint64_t offset,int nb_sectors);/* qcow2-snapshot.c functions */ -int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info); +int qcow2_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp);int qcow2_snapshot_goto (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab);
block/rbd.c +14 -6
@@ -16,6 +16,7 @@#include "qemu-common.h" #include "qemu-error.h" #include "block_int.h" +#include "qerror.h" #include <rbd/librbd.h>
@@ -817,12 +818,15 @@ static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset) }static int qemu_rbd_snap_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVRBDState *s = bs->opaque; -int r; +int ret;if (sn_info->name[0 ] =='\0' ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"some tag identifier" );return -EINVAL ;/* we need a name for rbd snapshots */ }
@@ -832,17 +836,21 @@ static int qemu_rbd_snap_create(BlockDriverState *bs,*/ if (sn_info->id_str[0 ] !='\0' &&strcmp (sn_info->id_str, sn_info->name) !=0 ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"id and tag to equal" );return -EINVAL ; }if (strlen (sn_info->name) >=sizeof (sn_info->id_str)) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"shorter than 127 chars" );return -ERANGE ; } - r =rbd_snap_create (s->image, sn_info->name); -if (r <0 ) { -error_report ("failed to create snap: %s" ,strerror (-r)); -return r; + ret =rbd_snap_create (s->image, sn_info->name); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); +return ret; }return 0 ;
block/sheepdog.c +9 -8
@@ -17,6 +17,7 @@#include "qemu_socket.h" #include "block_int.h" #include "bitops.h" +#include "qerror.h" #define SD_PROTO_VER 0x01
@@ -1730,7 +1731,9 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)return 0 ; } -static int sd_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info) +static int sd_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVSheepdogState *s = bs->opaque;int ret, fd;
@@ -1743,9 +1746,8 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->name, sn_info->vm_state_size, s->is_snapshot);if (s->is_snapshot) { -error_report ("You can't create a snapshot of a snapshot VDI, " -"%s (%" PRIu32")." , s->name, s->inode.vdi_id); - +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ," not VDI snapshot" );return -EINVAL ; }
@@ -1767,15 +1769,12 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) ret =write_object (fd, (char *)&s->inode,vid_to_vdi_oid (s->inode.vdi_id), s->inode.nr_copies, datalen,0 ,0 , s->cache_enabled);if (ret <0 ) { -error_report ("failed to write snapshot's inode." ); goto cleanup; } ret =do_sd_create (s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid,1 , s->addr, s->port);if (ret <0 ) { -error_report ("failed to create inode for snapshot. %s" , -strerror (errno)); goto cleanup; }
@@ -1785,7 +1784,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->inode.nr_copies, datalen, 0, s->cache_enabled);if (ret <0 ) { -error_report ("failed to read new inode info. %s" ,strerror (errno)); goto cleanup; }
@@ -1795,6 +1793,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) cleanup:closesocket (fd); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; }
block_int.h +2 -1
@@ -206,7 +206,8 @@ struct BlockDriver { const uint8_t *buf, int nb_sectors);int (*bdrv_snapshot_create)(BlockDriverState *bs, -QEMUSnapshotInfo *sn_info); +QEMUSnapshotInfo *sn_info, +Error **errp);int (*bdrv_snapshot_goto)(BlockDriverState *bs,const char *snapshot_id);int (*bdrv_snapshot_delete)(BlockDriverState *bs,const char *snapshot_id);
qemu-img.c +1 -1
@@ -1267,7 +1267,7 @@ static int img_snapshot(int argc, char **argv) sn.date_sec = tv.tv_sec; sn.date_nsec = tv.tv_usec *1000 ; - ret =bdrv_snapshot_create (bs, &sn); + ret =bdrv_snapshot_create (bs, &sn,NULL );if (ret) {error_report ("Could not create snapshot '%s': %d (%s)" , snapshot_name, ret,strerror (-ret));
savevm.c +1 -1
@@ -2165,7 +2165,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)if (bdrv_can_snapshot (bs1)) {/* 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); + ret =bdrv_snapshot_create (bs1, sn,NULL );if (ret <0 ) {monitor_printf (mon,"Error while creating snapshot on '%s'\n" ,bdrv_get_device_name (bs1));
Signature · 1 line
1.7.11.2
Re: [Qemu-devel] [PATCH 02/18] block: add error parameter to bdrv_snapshot_create() and related functions
Quoted 27 lines · On Wed, 15 Aug 2012 09:41:43 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- block.c | 25 +++++++++++++++++-------- block.h | 3 ++- block/qcow2-snapshot.c | 9 ++++++++- block/qcow2.h | 4 +++- block/rbd.c | 20 ++++++++++++++------ block/sheepdog.c | 17 +++++++++-------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 57 insertions(+), 28 deletions(-)block.c +2
-2@@ -2661,16 +2661,25 @@ BlockDriverState *bdrv_snapshots(void) }int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv)
block.c BlockDriverState *bdrv_snapshots(void) · line 2671
Quoted 10 lines
block.c +4
-6-return -ENOMEDIUM ; -if (drv->bdrv_snapshot_create) -return drv->bdrv_snapshot_create (bs, sn_info); -if (bs->file) -return bdrv_snapshot_create (bs->file, sn_info); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs));
We should only use QERR_ macros for the errors listed in the ErrorClass enum (except GenericError), all other errors should generally use error_setg(), like this:
error_setg(errp, "device '%s' has no medium);
block.c BlockDriverState *bdrv_snapshots(void) · line 2672
Quoted 1 line
block.c +1
-0+ ret = -ENOMEDIUM ;
And, usually, we should get rid of errno propagation. There are two cases here:
1. errno is propagated up so that upper layers can print a decent error message to the user.
In this case, it's safe to eliminate errno. error_setg() will store a decent message already and the Error object can be propagated up.
2. errno is propagated up so that upper layers can distinguish among error causes and take different actions accordingly.
Doesn't seem to be the case of bdrv_snapshot_create() (ie. errno is only used to communicate the error to the user). However, I'm pretty sure that such usage exists in qemu and the error API will break it, as most of our errors are generic.
I see two solutions to this problem:
A. Add specific errors to ErrorClass. I don't like this very much,
as it's possible that such errors are going to be useful only internally.
B. Add two new functions:
void error_sete(Error **err, ErrorClass err_class, int errno, const char *fmt, ...); int error_get_errno(const Error **err);
So that we can maintain errno when it's used to communicate error cause among functions.
Quoted 126 lines
block.c +10
-0+ }else if (drv->bdrv_snapshot_create) { + ret = drv->bdrv_snapshot_create (bs, sn_info, errp); + }else if (bs->file) { + ret =bdrv_snapshot_create (bs->file, sn_info, errp); + }else { +error_set (errp,QERR_NOT_SUPPORTED ); + ret = -ENOTSUP ; + } + +return ret; } int bdrv_snapshot_goto(BlockDriverState *bs,block.h +2
-1@@ -296,7 +296,8 @@ int bdrv_can_snapshot(BlockDriverState *bs);int bdrv_is_snapshot (BlockDriverState *bs);BlockDriverState *bdrv_snapshots (void );int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info); +QEMUSnapshotInfo *sn_info, +Error **errp);int bdrv_snapshot_goto (BlockDriverState *bs,const char *snapshot_id);int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);block/qcow2-snapshot.c +8
-1@@ -25,6 +25,7 @@#include "qemu-common.h" #include "block_int.h" #include "block/qcow2.h" +#include "qerror.h" typedef struct QEMU_PACKED QCowSnapshotHeader {/* header is 8 byte aligned */ @@ -312,7 +313,9 @@ static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name) }/* if no id is provided, a new one is constructed */ -int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info) +int qcow2_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVQcowState *s = bs->opaque;QCowSnapshot *new_snapshot_list =NULL ;@@ -331,6 +334,8 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)/* Check that the ID is unique */ if (find_snapshot_by_id (bs, sn_info->id_str) >=0 ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"non-existing id identifier" );return -EEXIST ; }@@ -415,6 +420,8 @@ fail:g_free (sn->name);g_free (l1_table); +error_set (errp,QERR_GENERIC_ERROR , ret); +return ret; }block/qcow2.h +3
-1@@ -308,7 +308,9 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,int qcow2_zero_clusters (BlockDriverState *bs,uint64_t offset,int nb_sectors);/* qcow2-snapshot.c functions */ -int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info); +int qcow2_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp);int qcow2_snapshot_goto (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab);block/rbd.c +10
-2@@ -16,6 +16,7 @@#include "qemu-common.h" #include "qemu-error.h" #include "block_int.h" +#include "qerror.h" #include <rbd/librbd.h> @@ -817,12 +818,15 @@ static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset) }static int qemu_rbd_snap_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVRBDState *s = bs->opaque; -int r; +int ret;if (sn_info->name[0 ] =='\0' ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"some tag identifier" );return -EINVAL ;/* we need a name for rbd snapshots */ }@@ -832,17 +836,21 @@ static int qemu_rbd_snap_create(BlockDriverState *bs,*/ if (sn_info->id_str[0 ] !='\0' &&strcmp (sn_info->id_str, sn_info->name) !=0 ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"id and tag to equal" );return -EINVAL ; }if (strlen (sn_info->name) >=sizeof (sn_info->id_str)) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"shorter than 127 chars" );return -ERANGE ;
block/rbd.c static int qemu_rbd_snap_create(BlockDriverState *bs, · line 853
Quoted 10 lines
block/rbd.c +4
-4} - r =rbd_snap_create (s->image, sn_info->name); -if (r <0 ) { -error_report ("failed to create snap: %s" ,strerror (-r)); -return r; + ret =rbd_snap_create (s->image, sn_info->name); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); +return ret;
You should always be careful when dropping error_report(), most of the time you also have to change callers. In this case, bdrv_snapshot_create() is called by qemu-img, which should be changed to print the error from the Error object.
Quoted 112 lines
block/rbd.c +0
-0}return 0 ;block/sheepdog.c +9
-8@@ -17,6 +17,7 @@#include "qemu_socket.h" #include "block_int.h" #include "bitops.h" +#include "qerror.h" #define SD_PROTO_VER 0x01@@ -1730,7 +1731,9 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)return 0 ; } -static int sd_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info) +static int sd_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVSheepdogState *s = bs->opaque;int ret, fd;@@ -1743,9 +1746,8 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->name, sn_info->vm_state_size, s->is_snapshot);if (s->is_snapshot) { -error_report ("You can't create a snapshot of a snapshot VDI, " -"%s (%" PRIu32")." , s->name, s->inode.vdi_id); - +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ," not VDI snapshot" );return -EINVAL ; }@@ -1767,15 +1769,12 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) ret =write_object (fd, (char *)&s->inode,vid_to_vdi_oid (s->inode.vdi_id), s->inode.nr_copies, datalen,0 ,0 , s->cache_enabled);if (ret <0 ) { -error_report ("failed to write snapshot's inode." ); goto cleanup; } ret =do_sd_create (s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid,1 , s->addr, s->port);if (ret <0 ) { -error_report ("failed to create inode for snapshot. %s" , -strerror (errno)); goto cleanup; }@@ -1785,7 +1784,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->inode.nr_copies, datalen, 0, s->cache_enabled);if (ret <0 ) { -error_report ("failed to read new inode info. %s" ,strerror (errno)); goto cleanup; }@@ -1795,6 +1793,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) cleanup:closesocket (fd); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; }block_int.h +2
-1@@ -206,7 +206,8 @@ struct BlockDriver { const uint8_t *buf, int nb_sectors);int (*bdrv_snapshot_create)(BlockDriverState *bs, -QEMUSnapshotInfo *sn_info); +QEMUSnapshotInfo *sn_info, +Error **errp);int (*bdrv_snapshot_goto)(BlockDriverState *bs,const char *snapshot_id);int (*bdrv_snapshot_delete)(BlockDriverState *bs,const char *snapshot_id);qemu-img.c +1
-1@@ -1267,7 +1267,7 @@ static int img_snapshot(int argc, char **argv) sn.date_sec = tv.tv_sec; sn.date_nsec = tv.tv_usec *1000 ; - ret =bdrv_snapshot_create (bs, &sn); + ret =bdrv_snapshot_create (bs, &sn,NULL );if (ret) {error_report ("Could not create snapshot '%s': %d (%s)" , snapshot_name, ret,strerror (-ret));savevm.c +1
-1@@ -2165,7 +2165,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)if (bdrv_can_snapshot (bs1)) {/* 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); + ret =bdrv_snapshot_create (bs1, sn,NULL );if (ret <0 ) {monitor_printf (mon,"Error while creating snapshot on '%s'\n" ,bdrv_get_device_name (bs1));
Re: [Qemu-devel] [PATCH 02/18] block: add error parameter to bdrv_snapshot_create() and related functions
Quoted 45 lines · Luiz Capitulino
Quoted 27 lines · On Wed, 15 Aug 2012 09:41:43 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- block.c | 25 +++++++++++++++++-------- block.h | 3 ++- block/qcow2-snapshot.c | 9 ++++++++- block/qcow2.h | 4 +++- block/rbd.c | 20 ++++++++++++++------ block/sheepdog.c | 17 +++++++++-------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 57 insertions(+), 28 deletions(-)block.c +2
-2@@ -2661,16 +2661,25 @@ BlockDriverState *bdrv_snapshots(void) }int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv)block.c BlockDriverState *bdrv_snapshots(void) · line 2671
Quoted 10 lines
block.c +4
-6-return -ENOMEDIUM ; -if (drv->bdrv_snapshot_create) -return drv->bdrv_snapshot_create (bs, sn_info); -if (bs->file) -return bdrv_snapshot_create (bs->file, sn_info); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs));We should only use
QERR_macros for the errors listed in the ErrorClass enum (except GenericError), all other errors should generally useerror_setg(), like this:
Quoted 5 lines
error_setg(errp, "device '%s' has no medium);block.c BlockDriverState *bdrv_snapshots(void) · line 2672
Quoted 1 line
block.c +1
-0+ ret = -ENOMEDIUM ;And, usually, we should get rid of errno propagation. There are two cases here:
The block layer consistently[*] uses -errno return values. Its consistency is valuable, and I'm a bit reluctant to break it. Maybe a new rule "returns -errno, except when it has an Error ** argument" could work. I'd like to hear Kevin's advice on this.
Quoted 15 lines
1. errno is propagated up so that upper layers can print a decent error message to the user.
In this case, it's safe to eliminate errno.
error_setg()will store a decent message already and the Error object can be propagated up.2. errno is propagated up so that upper layers can distinguish among error causes and take different actions accordingly.
Doesn't seem to be the case of
bdrv_snapshot_create()(ie. errno is only used to communicate the error to the user). However, I'm pretty sure that such usage exists in qemu and the error API will break it, as most of our errors are generic.
Quoted 4 lines
I see two solutions to this problem:
A. Add specific errors to ErrorClass. I don't like this very much,
as it's possible that such errors are going to be useful only internally.
Let's not reinvent errno, poorly.
Quoted 7 lines
B. Add two new functions:
void
error_sete(Error **err, ErrorClass err_class, int errno, const char *fmt, ...); interror_get_errno(const Error **err);So that we can maintain errno when it's used to communicate error cause among functions.
Better.
What's ErrorClass doing there?
[...]
[*] Almost; it's still QEMU after all.
Re: [Qemu-devel] [PATCH 02/18] block: add error parameter to bdrv_snapshot_create() and related functions
Am 31.08.2012 08:26, schrieb Markus Armbruster:
Quoted 49 lines
Quoted 47 lines · Luiz Capitulino
Quoted 27 lines · On Wed, 15 Aug 2012 09:41:43 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- block.c | 25 +++++++++++++++++-------- block.h | 3 ++- block/qcow2-snapshot.c | 9 ++++++++- block/qcow2.h | 4 +++- block/rbd.c | 20 ++++++++++++++------ block/sheepdog.c | 17 +++++++++-------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 57 insertions(+), 28 deletions(-)block.c +2
-2@@ -2661,16 +2661,25 @@ BlockDriverState *bdrv_snapshots(void) }int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv)block.c BlockDriverState *bdrv_snapshots(void) · line 2671
Quoted 10 lines
block.c +4
-6-return -ENOMEDIUM ; -if (drv->bdrv_snapshot_create) -return drv->bdrv_snapshot_create (bs, sn_info); -if (bs->file) -return bdrv_snapshot_create (bs->file, sn_info); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs));We should only use
QERR_macros for the errors listed in the ErrorClass enum (except GenericError), all other errors should generally useerror_setg(), like this:
error_setg(errp, "device '%s' has no medium);
Quoted 8 lines
Quoted 3 lines
block.c BlockDriverState *bdrv_snapshots(void) · line 2672
Quoted 1 line
block.c +1
-0+ ret = -ENOMEDIUM ;And, usually, we should get rid of errno propagation. There are two cases here:
The block layer consistently[*] uses -errno return values. Its consistency is valuable, and I'm a bit reluctant to break it. Maybe a new rule "returns -errno, except when it has an Error ** argument" could work. I'd like to hear Kevin's advice on this.
I'd rather not remove existing -errno returns if there's not good reason why we can't provide them (or can't do so easily at least).
Kevin
Re: [Qemu-devel] [PATCH 02/18] block: add error parameter to bdrv_snapshot_create() and related functions
Quoted 54 lines · On Fri, 31 Aug 2012 14:18:55 +0200 Kevin Wolf <[email protected]> wrote:
Am 31.08.2012 08:26, schrieb Markus Armbruster:
Quoted 53 lines
Quoted 50 lines · Luiz Capitulino
Quoted 27 lines · On Wed, 15 Aug 2012 09:41:43 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- block.c | 25 +++++++++++++++++-------- block.h | 3 ++- block/qcow2-snapshot.c | 9 ++++++++- block/qcow2.h | 4 +++- block/rbd.c | 20 ++++++++++++++------ block/sheepdog.c | 17 +++++++++-------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 57 insertions(+), 28 deletions(-)block.c +2
-2@@ -2661,16 +2661,25 @@ BlockDriverState *bdrv_snapshots(void) }int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv)block.c BlockDriverState *bdrv_snapshots(void) · line 2671
Quoted 10 lines
block.c +4
-6-return -ENOMEDIUM ; -if (drv->bdrv_snapshot_create) -return drv->bdrv_snapshot_create (bs, sn_info); -if (bs->file) -return bdrv_snapshot_create (bs->file, sn_info); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs));We should only use
QERR_macros for the errors listed in the ErrorClass enum (except GenericError), all other errors should generally useerror_setg(), like this:
error_setg(errp, "device '%s' has no medium);block.c BlockDriverState *bdrv_snapshots(void) · line 2672
Quoted 1 line
block.c +1
-0+ ret = -ENOMEDIUM ;And, usually, we should get rid of errno propagation. There are two cases here:
Quoted 7 lines
Quoted 4 lines
The block layer consistently[*] uses -errno return values. Its consistency is valuable, and I'm a bit reluctant to break it. Maybe a new rule "returns -errno, except when it has an Error ** argument" could work. I'd like to hear Kevin's advice on this.
I'd rather not remove existing -errno returns if there's not good reason why we can't provide them (or can't do so easily at least).
Yes, I agree. Let me evaluate this calmly. I'll try to come with a better proposal soon.
Re: [Qemu-devel] [PATCH 02/18] block: add error parameter to bdrv_snapshot_create() and related functions
In reply to Markus ArmbrusterQuoted 85 lines · On Fri, 31 Aug 2012 08:26:38 +0200 Markus Armbruster <[email protected]> wrote:
Quoted 45 lines · Luiz Capitulino
Quoted 27 lines · On Wed, 15 Aug 2012 09:41:43 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- block.c | 25 +++++++++++++++++-------- block.h | 3 ++- block/qcow2-snapshot.c | 9 ++++++++- block/qcow2.h | 4 +++- block/rbd.c | 20 ++++++++++++++------ block/sheepdog.c | 17 +++++++++-------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 57 insertions(+), 28 deletions(-)block.c +2
-2@@ -2661,16 +2661,25 @@ BlockDriverState *bdrv_snapshots(void) }int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv)block.c BlockDriverState *bdrv_snapshots(void) · line 2671
Quoted 10 lines
block.c +4
-6-return -ENOMEDIUM ; -if (drv->bdrv_snapshot_create) -return drv->bdrv_snapshot_create (bs, sn_info); -if (bs->file) -return bdrv_snapshot_create (bs->file, sn_info); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs));We should only use
QERR_macros for the errors listed in the ErrorClass enum (except GenericError), all other errors should generally useerror_setg(), like this:Quoted 5 lines
error_setg(errp, "device '%s' has no medium);block.c BlockDriverState *bdrv_snapshots(void) · line 2672
Quoted 1 line
block.c +1
-0+ ret = -ENOMEDIUM ;And, usually, we should get rid of errno propagation. There are two cases here:
The block layer consistently[*] uses -errno return values. Its consistency is valuable, and I'm a bit reluctant to break it. Maybe a new rule "returns -errno, except when it has an Error ** argument" could work. I'd like to hear Kevin's advice on this.
Quoted 15 lines
1. errno is propagated up so that upper layers can print a decent error message to the user.
In this case, it's safe to eliminate errno.
error_setg()will store a decent message already and the Error object can be propagated up.2. errno is propagated up so that upper layers can distinguish among error causes and take different actions accordingly.
Doesn't seem to be the case of
bdrv_snapshot_create()(ie. errno is only used to communicate the error to the user). However, I'm pretty sure that such usage exists in qemu and the error API will break it, as most of our errors are generic.Quoted 4 lines
I see two solutions to this problem:
A. Add specific errors to ErrorClass. I don't like this very much,
as it's possible that such errors are going to be useful only internally.Let's not reinvent errno, poorly.
Quoted 5 lines
B. Add two new functions: void error_sete(Error **err, ErrorClass err_class, int errno, const char *fmt, ...); int error_get_errno(const Error **err);
Quoted 6 lines
Quoted 2 lines
So that we can maintain errno when it's used to communicate error cause among functions.
Better.
What's ErrorClass doing there?
There might be cases where we will have to report an error other than GenericError, we could have error_sete_generic(), but this is starting to get weird :)
Quoted 6 lines
[...]
[*] Almost; it's still QEMU after all.
Re: [Qemu-devel] [PATCH 02/18] block: add error parameter to bdrv_snapshot_create() and related functions
In reply to Luiz CapitulinoQuoted 44 lines · Luiz Capitulino
Quoted 27 lines · On Wed, 15 Aug 2012 09:41:43 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- block.c | 25 +++++++++++++++++-------- block.h | 3 ++- block/qcow2-snapshot.c | 9 ++++++++- block/qcow2.h | 4 +++- block/rbd.c | 20 ++++++++++++++------ block/sheepdog.c | 17 +++++++++-------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 57 insertions(+), 28 deletions(-)block.c +2
-2@@ -2661,16 +2661,25 @@ BlockDriverState *bdrv_snapshots(void) }int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv)block.c BlockDriverState *bdrv_snapshots(void) · line 2671
Quoted 10 lines
block.c +4
-6-return -ENOMEDIUM ; -if (drv->bdrv_snapshot_create) -return drv->bdrv_snapshot_create (bs, sn_info); -if (bs->file) -return bdrv_snapshot_create (bs->file, sn_info); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs));We should only use
QERR_macros for the errors listed in the ErrorClass enum (except GenericError), all other errors should generally useerror_setg(), like this:
Quoted 1 line
error_setg(errp, "device '%s' has no medium);
I agree that we should use error_setg() for all GenericError, but I think that would be better have macros for errors which are used many-times . For example:
#define QERR_ERRMSG_DEVICE_HAS_NO_MEDIUM "Device '%s' has no medium"
and use error_setg(errp, QERR_ERRMSG_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
I think that the consistency of error messages is important and an error message should be the same for every error occurrence.
Quoted 283 lines
block.c BlockDriverState *bdrv_snapshots(void) · line 2672
Quoted 2 lines
block.c +1
-0+ ret = -ENOMEDIUM ;And, usually, we should get rid of errno propagation. There are two cases here:
1. errno is propagated up so that upper layers can print a decent error message to the user.
In this case, it's safe to eliminate errno.
error_setg()will store a decent message already and the Error object can be propagated up.2. errno is propagated up so that upper layers can distinguish among error causes and take different actions accordingly.
Doesn't seem to be the case of
bdrv_snapshot_create()(ie. errno is only used to communicate the error to the user). However, I'm pretty sure that such usage exists in qemu and the error API will break it, as most of our errors are generic.I see two solutions to this problem:
A. Add specific errors to ErrorClass. I don't like this very much,
as it's possible that such errors are going to be useful only internally.B. Add two new functions:
void
error_sete(Error **err, ErrorClass err_class, int errno, const char *fmt, ...); interror_get_errno(const Error **err);So that we can maintain errno when it's used to communicate error cause among functions.
Quoted 126 lines
block.c +10
-0+ }else if (drv->bdrv_snapshot_create) { + ret = drv->bdrv_snapshot_create (bs, sn_info, errp); + }else if (bs->file) { + ret =bdrv_snapshot_create (bs->file, sn_info, errp); + }else { +error_set (errp,QERR_NOT_SUPPORTED ); + ret = -ENOTSUP ; + } + +return ret; } int bdrv_snapshot_goto(BlockDriverState *bs,block.h +2
-1@@ -296,7 +296,8 @@ int bdrv_can_snapshot(BlockDriverState *bs);int bdrv_is_snapshot (BlockDriverState *bs);BlockDriverState *bdrv_snapshots (void );int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info); +QEMUSnapshotInfo *sn_info, +Error **errp);int bdrv_snapshot_goto (BlockDriverState *bs,const char *snapshot_id);int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);block/qcow2-snapshot.c +8
-1@@ -25,6 +25,7 @@#include "qemu-common.h" #include "block_int.h" #include "block/qcow2.h" +#include "qerror.h" typedef struct QEMU_PACKED QCowSnapshotHeader {/* header is 8 byte aligned */ @@ -312,7 +313,9 @@ static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name) }/* if no id is provided, a new one is constructed */ -int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info) +int qcow2_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVQcowState *s = bs->opaque;QCowSnapshot *new_snapshot_list =NULL ;@@ -331,6 +334,8 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)/* Check that the ID is unique */ if (find_snapshot_by_id (bs, sn_info->id_str) >=0 ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"non-existing id identifier" );return -EEXIST ; }@@ -415,6 +420,8 @@ fail:g_free (sn->name);g_free (l1_table); +error_set (errp,QERR_GENERIC_ERROR , ret); +return ret; }block/qcow2.h +3
-1@@ -308,7 +308,9 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,int qcow2_zero_clusters (BlockDriverState *bs,uint64_t offset,int nb_sectors);/* qcow2-snapshot.c functions */ -int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info); +int qcow2_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp);int qcow2_snapshot_goto (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab);block/rbd.c +10
-2@@ -16,6 +16,7 @@#include "qemu-common.h" #include "qemu-error.h" #include "block_int.h" +#include "qerror.h" #include <rbd/librbd.h> @@ -817,12 +818,15 @@ static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset) }static int qemu_rbd_snap_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVRBDState *s = bs->opaque; -int r; +int ret;if (sn_info->name[0 ] =='\0' ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"some tag identifier" );return -EINVAL ;/* we need a name for rbd snapshots */ }@@ -832,17 +836,21 @@ static int qemu_rbd_snap_create(BlockDriverState *bs,*/ if (sn_info->id_str[0 ] !='\0' &&strcmp (sn_info->id_str, sn_info->name) !=0 ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"id and tag to equal" );return -EINVAL ; }if (strlen (sn_info->name) >=sizeof (sn_info->id_str)) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"shorter than 127 chars" );return -ERANGE ;block/rbd.c static int qemu_rbd_snap_create(BlockDriverState *bs, · line 853
Quoted 10 lines
block/rbd.c +4
-4} - r =rbd_snap_create (s->image, sn_info->name); -if (r <0 ) { -error_report ("failed to create snap: %s" ,strerror (-r)); -return r; + ret =rbd_snap_create (s->image, sn_info->name); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); +return ret;You should always be careful when dropping
error_report(), most of the time you also have to change callers. In this case,bdrv_snapshot_create()is called by qemu-img, which should be changed to print the error from the Error object.Quoted 112 lines
block/rbd.c +0
-0}return 0 ;block/sheepdog.c +9
-8@@ -17,6 +17,7 @@#include "qemu_socket.h" #include "block_int.h" #include "bitops.h" +#include "qerror.h" #define SD_PROTO_VER 0x01@@ -1730,7 +1731,9 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)return 0 ; } -static int sd_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info) +static int sd_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVSheepdogState *s = bs->opaque;int ret, fd;@@ -1743,9 +1746,8 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->name, sn_info->vm_state_size, s->is_snapshot);if (s->is_snapshot) { -error_report ("You can't create a snapshot of a snapshot VDI, " -"%s (%" PRIu32")." , s->name, s->inode.vdi_id); - +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ," not VDI snapshot" );return -EINVAL ; }@@ -1767,15 +1769,12 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) ret =write_object (fd, (char *)&s->inode,vid_to_vdi_oid (s->inode.vdi_id), s->inode.nr_copies, datalen,0 ,0 , s->cache_enabled);if (ret <0 ) { -error_report ("failed to write snapshot's inode." ); goto cleanup; } ret =do_sd_create (s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid,1 , s->addr, s->port);if (ret <0 ) { -error_report ("failed to create inode for snapshot. %s" , -strerror (errno)); goto cleanup; }@@ -1785,7 +1784,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->inode.nr_copies, datalen, 0, s->cache_enabled);if (ret <0 ) { -error_report ("failed to read new inode info. %s" ,strerror (errno)); goto cleanup; }@@ -1795,6 +1793,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) cleanup:closesocket (fd); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; }block_int.h +2
-1@@ -206,7 +206,8 @@ struct BlockDriver { const uint8_t *buf, int nb_sectors);int (*bdrv_snapshot_create)(BlockDriverState *bs, -QEMUSnapshotInfo *sn_info); +QEMUSnapshotInfo *sn_info, +Error **errp);int (*bdrv_snapshot_goto)(BlockDriverState *bs,const char *snapshot_id);int (*bdrv_snapshot_delete)(BlockDriverState *bs,const char *snapshot_id);qemu-img.c +1
-1@@ -1267,7 +1267,7 @@ static int img_snapshot(int argc, char **argv) sn.date_sec = tv.tv_sec; sn.date_nsec = tv.tv_usec *1000 ; - ret =bdrv_snapshot_create (bs, &sn); + ret =bdrv_snapshot_create (bs, &sn,NULL );if (ret) {error_report ("Could not create snapshot '%s': %d (%s)" , snapshot_name, ret,strerror (-ret));savevm.c +1
-1@@ -2165,7 +2165,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)if (bdrv_can_snapshot (bs1)) {/* 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); + ret =bdrv_snapshot_create (bs1, sn,NULL );if (ret <0 ) {monitor_printf (mon,"Error while creating snapshot on '%s'\n" ,bdrv_get_device_name (bs1));
Re: [Qemu-devel] [PATCH 02/18] block: add error parameter to bdrv_snapshot_create() and related functions
Quoted 47 lines · On Thu, 06 Sep 2012 11:07:54 +0200 Pavel Hrdina <[email protected]> wrote:
Quoted 44 lines · Luiz Capitulino
Quoted 27 lines · On Wed, 15 Aug 2012 09:41:43 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- block.c | 25 +++++++++++++++++-------- block.h | 3 ++- block/qcow2-snapshot.c | 9 ++++++++- block/qcow2.h | 4 +++- block/rbd.c | 20 ++++++++++++++------ block/sheepdog.c | 17 +++++++++-------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 57 insertions(+), 28 deletions(-)block.c +2
-2@@ -2661,16 +2661,25 @@ BlockDriverState *bdrv_snapshots(void) }int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv)block.c BlockDriverState *bdrv_snapshots(void) · line 2671
Quoted 10 lines
block.c +4
-6-return -ENOMEDIUM ; -if (drv->bdrv_snapshot_create) -return drv->bdrv_snapshot_create (bs, sn_info); -if (bs->file) -return bdrv_snapshot_create (bs->file, sn_info); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs));We should only use
QERR_macros for the errors listed in the ErrorClass enum (except GenericError), all other errors should generally useerror_setg(), like this:Quoted 1 line
error_setg(errp, "device '%s' has no medium);
Quoted 8 lines
I agree that we should use
error_setg()for all GenericError, but I think that would be better have macros for errors which are used many-times . For example:#define
QERR_ERRMSG_DEVICE_HAS_NO_MEDIUM"Device '%s' has no medium"and use
error_setg(errp, QERR_ERRMSG_DEVICE_HAS_NO_MEDIUM, bdrv_get_device_name(bs));
Hmm, no. The best way to refactor code that use the same error message like the one above is to move the whole operation (with error handling included) to a wrapper and use the wrapper instead.
Adding macros for error messages is a Bad Thing because soon or later someone will create a new macro for a very similar but different error message (which will lead to macro explosion) or will use an existing macro that doesn't fit well to the failure being reported.
Quoted 287 lines
I think that the consistency of error messages is important and an error message should be the same for every error occurrence.
Quoted 283 lines
block.c BlockDriverState *bdrv_snapshots(void) · line 2672
Quoted 2 lines
block.c +1
-0+ ret = -ENOMEDIUM ;And, usually, we should get rid of errno propagation. There are two cases here:
1. errno is propagated up so that upper layers can print a decent error message to the user.
In this case, it's safe to eliminate errno.
error_setg()will store a decent message already and the Error object can be propagated up.2. errno is propagated up so that upper layers can distinguish among error causes and take different actions accordingly.
Doesn't seem to be the case of
bdrv_snapshot_create()(ie. errno is only used to communicate the error to the user). However, I'm pretty sure that such usage exists in qemu and the error API will break it, as most of our errors are generic.I see two solutions to this problem:
A. Add specific errors to ErrorClass. I don't like this very much,
as it's possible that such errors are going to be useful only internally.B. Add two new functions:
void
error_sete(Error **err, ErrorClass err_class, int errno, const char *fmt, ...); interror_get_errno(const Error **err);So that we can maintain errno when it's used to communicate error cause among functions.
Quoted 126 lines
block.c +10
-0+ }else if (drv->bdrv_snapshot_create) { + ret = drv->bdrv_snapshot_create (bs, sn_info, errp); + }else if (bs->file) { + ret =bdrv_snapshot_create (bs->file, sn_info, errp); + }else { +error_set (errp,QERR_NOT_SUPPORTED ); + ret = -ENOTSUP ; + } + +return ret; } int bdrv_snapshot_goto(BlockDriverState *bs,block.h +2
-1@@ -296,7 +296,8 @@ int bdrv_can_snapshot(BlockDriverState *bs);int bdrv_is_snapshot (BlockDriverState *bs);BlockDriverState *bdrv_snapshots (void );int bdrv_snapshot_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info); +QEMUSnapshotInfo *sn_info, +Error **errp);int bdrv_snapshot_goto (BlockDriverState *bs,const char *snapshot_id);int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);block/qcow2-snapshot.c +8
-1@@ -25,6 +25,7 @@#include "qemu-common.h" #include "block_int.h" #include "block/qcow2.h" +#include "qerror.h" typedef struct QEMU_PACKED QCowSnapshotHeader {/* header is 8 byte aligned */ @@ -312,7 +313,9 @@ static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name) }/* if no id is provided, a new one is constructed */ -int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info) +int qcow2_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVQcowState *s = bs->opaque;QCowSnapshot *new_snapshot_list =NULL ;@@ -331,6 +334,8 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)/* Check that the ID is unique */ if (find_snapshot_by_id (bs, sn_info->id_str) >=0 ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"non-existing id identifier" );return -EEXIST ; }@@ -415,6 +420,8 @@ fail:g_free (sn->name);g_free (l1_table); +error_set (errp,QERR_GENERIC_ERROR , ret); +return ret; }block/qcow2.h +3
-1@@ -308,7 +308,9 @@ int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,int qcow2_zero_clusters (BlockDriverState *bs,uint64_t offset,int nb_sectors);/* qcow2-snapshot.c functions */ -int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info); +int qcow2_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp);int qcow2_snapshot_goto (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab);block/rbd.c +10
-2@@ -16,6 +16,7 @@#include "qemu-common.h" #include "qemu-error.h" #include "block_int.h" +#include "qerror.h" #include <rbd/librbd.h> @@ -817,12 +818,15 @@ static int qemu_rbd_truncate(BlockDriverState *bs, int64_t offset) }static int qemu_rbd_snap_create (BlockDriverState *bs, -QEMUSnapshotInfo *sn_info) +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVRBDState *s = bs->opaque; -int r; +int ret;if (sn_info->name[0 ] =='\0' ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"some tag identifier" );return -EINVAL ;/* we need a name for rbd snapshots */ }@@ -832,17 +836,21 @@ static int qemu_rbd_snap_create(BlockDriverState *bs,*/ if (sn_info->id_str[0 ] !='\0' &&strcmp (sn_info->id_str, sn_info->name) !=0 ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"id and tag to equal" );return -EINVAL ; }if (strlen (sn_info->name) >=sizeof (sn_info->id_str)) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"shorter than 127 chars" );return -ERANGE ;block/rbd.c static int qemu_rbd_snap_create(BlockDriverState *bs, · line 853
Quoted 10 lines
block/rbd.c +4
-4} - r =rbd_snap_create (s->image, sn_info->name); -if (r <0 ) { -error_report ("failed to create snap: %s" ,strerror (-r)); -return r; + ret =rbd_snap_create (s->image, sn_info->name); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); +return ret;You should always be careful when dropping
error_report(), most of the time you also have to change callers. In this case,bdrv_snapshot_create()is called by qemu-img, which should be changed to print the error from the Error object.Quoted 112 lines
block/rbd.c +0
-0}return 0 ;block/sheepdog.c +9
-8@@ -17,6 +17,7 @@#include "qemu_socket.h" #include "block_int.h" #include "bitops.h" +#include "qerror.h" #define SD_PROTO_VER 0x01@@ -1730,7 +1731,9 @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)return 0 ; } -static int sd_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info) +static int sd_snapshot_create (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +Error **errp) {BDRVSheepdogState *s = bs->opaque;int ret, fd;@@ -1743,9 +1746,8 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->name, sn_info->vm_state_size, s->is_snapshot);if (s->is_snapshot) { -error_report ("You can't create a snapshot of a snapshot VDI, " -"%s (%" PRIu32")." , s->name, s->inode.vdi_id); - +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ," not VDI snapshot" );return -EINVAL ; }@@ -1767,15 +1769,12 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) ret =write_object (fd, (char *)&s->inode,vid_to_vdi_oid (s->inode.vdi_id), s->inode.nr_copies, datalen,0 ,0 , s->cache_enabled);if (ret <0 ) { -error_report ("failed to write snapshot's inode." ); goto cleanup; } ret =do_sd_create (s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid,1 , s->addr, s->port);if (ret <0 ) { -error_report ("failed to create inode for snapshot. %s" , -strerror (errno)); goto cleanup; }@@ -1785,7 +1784,6 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) s->inode.nr_copies, datalen, 0, s->cache_enabled);if (ret <0 ) { -error_report ("failed to read new inode info. %s" ,strerror (errno)); goto cleanup; }@@ -1795,6 +1793,9 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) cleanup:closesocket (fd); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; }block_int.h +2
-1@@ -206,7 +206,8 @@ struct BlockDriver { const uint8_t *buf, int nb_sectors);int (*bdrv_snapshot_create)(BlockDriverState *bs, -QEMUSnapshotInfo *sn_info); +QEMUSnapshotInfo *sn_info, +Error **errp);int (*bdrv_snapshot_goto)(BlockDriverState *bs,const char *snapshot_id);int (*bdrv_snapshot_delete)(BlockDriverState *bs,const char *snapshot_id);qemu-img.c +1
-1@@ -1267,7 +1267,7 @@ static int img_snapshot(int argc, char **argv) sn.date_sec = tv.tv_sec; sn.date_nsec = tv.tv_usec *1000 ; - ret =bdrv_snapshot_create (bs, &sn); + ret =bdrv_snapshot_create (bs, &sn,NULL );if (ret) {error_report ("Could not create snapshot '%s': %d (%s)" , snapshot_name, ret,strerror (-ret));savevm.c +1
-1@@ -2165,7 +2165,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)if (bdrv_can_snapshot (bs1)) {/* 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); + ret =bdrv_snapshot_create (bs1, sn,NULL );if (ret <0 ) {monitor_printf (mon,"Error while creating snapshot on '%s'\n" ,bdrv_get_device_name (bs1));
PATCH 3/18 block: add error parameter to bdrv_snapshot_goto() and related functions
In reply to Pavel Hrdina--- block.c | 26 +++++++++++++++----------- block.h | 3 ++- block/qcow2-snapshot.c | 11 ++++++++--- block/qcow2.h | 4 +++- block/rbd.c | 6 +++++- block/sheepdog.c | 16 +++++++++------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 46 insertions(+), 27 deletions(-)
block.c +15 -11
@@ -2683,29 +2683,33 @@ int bdrv_snapshot_create(BlockDriverState *bs, }int bdrv_snapshot_goto (BlockDriverState *bs, -const char *snapshot_id) +const char *snapshot_id, +Error **errp) {BlockDriver *drv = bs->drv;int ret, open_ret; -if (!drv) -return -ENOMEDIUM ; -if (drv->bdrv_snapshot_goto) -return drv->bdrv_snapshot_goto (bs, snapshot_id); - -if (bs->file) { +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs)); + ret = -ENOMEDIUM ; + }else if (drv->bdrv_snapshot_goto) { + ret = drv->bdrv_snapshot_goto (bs, snapshot_id, errp); + }else if (bs->file) { drv->bdrv_close (bs); - ret =bdrv_snapshot_goto (bs->file, snapshot_id); + ret =bdrv_snapshot_goto (bs->file, snapshot_id, errp); open_ret = drv->bdrv_open (bs, bs->open_flags);if (open_ret <0 ) {bdrv_delete (bs->file); bs->drv =NULL ; -return open_ret; +error_set (errp,QERR_OPEN_FILE_FAILED ,bdrv_get_device_name (bs)); + ret = open_ret; } -return ret; + }else { +error_set (errp,QERR_NOT_SUPPORTED ); + ret = -ENOTSUP ; } -return -ENOTSUP ; +return ret; }int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id)
block.h +2 -1
@@ -299,7 +299,8 @@ int bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, Error **errp);int bdrv_snapshot_goto (BlockDriverState *bs, -const char *snapshot_id); +const char *snapshot_id, +Error **errp);int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);int bdrv_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_info);
block/qcow2-snapshot.c +8 -3
@@ -426,7 +426,9 @@ fail: }/* copy the snapshot 'snapshot_name' into the current disk image */ -int qcow2_snapshot_goto (BlockDriverState *bs,const char *snapshot_id) +int qcow2_snapshot_goto (BlockDriverState *bs, +const char *snapshot_id, +Error **errp) {BDRVQcowState *s = bs->opaque;QCowSnapshot *sn;
@@ -438,13 +440,13 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)/* Search the snapshot */ snapshot_index =find_snapshot_by_id_or_name (bs, snapshot_id);if (snapshot_index <0 ) { +error_set (errp,QERR_OPEN_FILE_FAILED , snapshot_id);return -ENOENT ; } sn = &s->snapshots[snapshot_index];if (sn->disk_size != bs->total_sectors *BDRV_SECTOR_SIZE ) { -error_report ("qcow2: Loading snapshots with different disk " -"size is not implemented" ); +error_set (errp,QERR_NOT_SUPPORTED ); ret = -ENOTSUP ; goto fail; }
@@ -536,6 +538,9 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) fail:g_free (sn_l1_table); +if (!error_is_set (errp)) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; }
block/qcow2.h +3 -1
@@ -311,7 +311,9 @@ int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors);int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info,Error **errp); -int qcow2_snapshot_goto (BlockDriverState *bs,const char *snapshot_id); +int qcow2_snapshot_goto (BlockDriverState *bs, +const char *snapshot_id, +Error **errp);int qcow2_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab);int qcow2_snapshot_load_tmp (BlockDriverState *bs,const char *snapshot_name);
block/rbd.c +5 -1
@@ -867,12 +867,16 @@ static int qemu_rbd_snap_remove(BlockDriverState *bs, }static int qemu_rbd_snap_rollback (BlockDriverState *bs, -const char *snapshot_name) +const char *snapshot_name, +Error **errp) {BDRVRBDState *s = bs->opaque;int r; r =rbd_snap_rollback (s->image, snapshot_name); +if (r <0 ) { +error_set (errp,QERR_GENERIC_ERROR , r); + }return r; }
block/sheepdog.c +9 -7
@@ -1799,7 +1799,9 @@ cleanup:return ret; } -static int sd_snapshot_goto (BlockDriverState *bs,const char *snapshot_id) +static int sd_snapshot_goto (BlockDriverState *bs, +const char *snapshot_id, +Error **errp) {BDRVSheepdogState *s = bs->opaque;BDRVSheepdogState *old_s;
@@ -1824,13 +1826,12 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) ret =find_vdi_name (s, vdi, snapid, tag, &vid,1 );if (ret) { -error_report ("Failed to find_vdi_name" ); +error_set (errp,QERR_OPEN_FILE_FAILED , vdi); goto out; } fd =connect_to_sdog (s->addr, s->port);if (fd <0 ) { -error_report ("failed to connect" ); ret = fd; goto out; }
@@ -1848,7 +1849,8 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)memcpy (&s->inode, buf,sizeof (s->inode));if (!s->inode.vm_state_size) { -error_report ("Invalid snapshot" ); +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"existing snapshot" ); ret = -ENOENT ; goto out; }
@@ -1864,9 +1866,9 @@ out:memcpy (s, old_s,sizeof (BDRVSheepdogState));g_free (buf);g_free (old_s); - -error_report ("failed to open. recover old bdrv_sd_state." ); - +if (!error_is_set (errp)) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; }
block_int.h +2 -1
@@ -209,7 +209,8 @@ struct BlockDriver { QEMUSnapshotInfo *sn_info, Error **errp);int (*bdrv_snapshot_goto)(BlockDriverState *bs, -const char *snapshot_id); +const char *snapshot_id, +Error **errp);int (*bdrv_snapshot_delete)(BlockDriverState *bs,const char *snapshot_id);int (*bdrv_snapshot_list)(BlockDriverState *bs,QEMUSnapshotInfo **psn_info);
qemu-img.c +1 -1
@@ -1275,7 +1275,7 @@ static int img_snapshot(int argc, char **argv)break ;case SNAPSHOT_APPLY : - ret =bdrv_snapshot_goto (bs, snapshot_name); + ret =bdrv_snapshot_goto (bs, snapshot_name,NULL );if (ret) {error_report ("Could not apply snapshot '%s': %d (%s)" , snapshot_name, ret,strerror (-ret));
savevm.c +1 -1
@@ -2256,7 +2256,7 @@ int load_vmstate(const char *name) bs =NULL ;while ((bs =bdrv_next (bs))) {if (bdrv_can_snapshot (bs)) { - ret =bdrv_snapshot_goto (bs, name); + ret =bdrv_snapshot_goto (bs, name,NULL );if (ret <0 ) {error_report ("Error %d while activating snapshot '%s' on '%s'" , ret, name,bdrv_get_device_name (bs));
Signature · 1 line
1.7.11.2
Re: [Qemu-devel] [PATCH 03/18] block: add error parameter to bdrv_snapshot_goto() and related functions
Quoted 27 lines · On Wed, 15 Aug 2012 09:41:44 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- block.c | 26 +++++++++++++++----------- block.h | 3 ++- block/qcow2-snapshot.c | 11 ++++++++--- block/qcow2.h | 4 +++- block/rbd.c | 6 +++++- block/sheepdog.c | 16 +++++++++------- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 2 +- 9 files changed, 46 insertions(+), 27 deletions(-)block.c +2
-1@@ -2683,29 +2683,33 @@ int bdrv_snapshot_create(BlockDriverState *bs, }int bdrv_snapshot_goto (BlockDriverState *bs, -const char *snapshot_id) +const char *snapshot_id, +Error **errp) {BlockDriver *drv = bs->drv;int ret, open_ret;
block.c int bdrv_snapshot_create(BlockDriverState *bs, · line 2694
Quoted 10 lines
block.c +3
-6-if (!drv) -return -ENOMEDIUM ; -if (drv->bdrv_snapshot_goto) -return drv->bdrv_snapshot_goto (bs, snapshot_id); - -if (bs->file) { +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs)); + ret = -ENOMEDIUM ;
Most of the comments I made in 02/18 apply for this patch (and probably the next ones too), so to summarize:
1. The QERR_ macros are deprecated, we should use error_setg() instead
2. As a general rule, only the Error object should be propagated up (ie. we shouldn't propagate the Error object _and_ errno). It's debatable if we can get rid of errno, if we can't then we'll have to extend the error API to embed errno.
We have to discuss this with block layer guys, preferably before doing large series.
One more comment below.
Quoted 104 lines
block.c +10
-4+ }else if (drv->bdrv_snapshot_goto) { + ret = drv->bdrv_snapshot_goto (bs, snapshot_id, errp); + }else if (bs->file) { drv->bdrv_close (bs); - ret =bdrv_snapshot_goto (bs->file, snapshot_id); + ret =bdrv_snapshot_goto (bs->file, snapshot_id, errp); open_ret = drv->bdrv_open (bs, bs->open_flags);if (open_ret <0 ) {bdrv_delete (bs->file); bs->drv =NULL ; -return open_ret; +error_set (errp,QERR_OPEN_FILE_FAILED ,bdrv_get_device_name (bs)); + ret = open_ret; } -return ret; + }else { +error_set (errp,QERR_NOT_SUPPORTED ); + ret = -ENOTSUP ; } -return -ENOTSUP ; +return ret; }int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id)block.h +2
-1@@ -299,7 +299,8 @@ int bdrv_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, Error **errp);int bdrv_snapshot_goto (BlockDriverState *bs, -const char *snapshot_id); +const char *snapshot_id, +Error **errp);int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);int bdrv_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_info);block/qcow2-snapshot.c +8
-3@@ -426,7 +426,9 @@ fail: }/* copy the snapshot 'snapshot_name' into the current disk image */ -int qcow2_snapshot_goto (BlockDriverState *bs,const char *snapshot_id) +int qcow2_snapshot_goto (BlockDriverState *bs, +const char *snapshot_id, +Error **errp) {BDRVQcowState *s = bs->opaque;QCowSnapshot *sn;@@ -438,13 +440,13 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)/* Search the snapshot */ snapshot_index =find_snapshot_by_id_or_name (bs, snapshot_id);if (snapshot_index <0 ) { +error_set (errp,QERR_OPEN_FILE_FAILED , snapshot_id);return -ENOENT ; } sn = &s->snapshots[snapshot_index];if (sn->disk_size != bs->total_sectors *BDRV_SECTOR_SIZE ) { -error_report ("qcow2: Loading snapshots with different disk " -"size is not implemented" ); +error_set (errp,QERR_NOT_SUPPORTED ); ret = -ENOTSUP ; goto fail; }@@ -536,6 +538,9 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) fail:g_free (sn_l1_table); +if (!error_is_set (errp)) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; }block/qcow2.h +3
-1@@ -311,7 +311,9 @@ int qcow2_zero_clusters(BlockDriverState *bs, uint64_t offset, int nb_sectors);int qcow2_snapshot_create (BlockDriverState *bs,QEMUSnapshotInfo *sn_info,Error **errp); -int qcow2_snapshot_goto (BlockDriverState *bs,const char *snapshot_id); +int qcow2_snapshot_goto (BlockDriverState *bs, +const char *snapshot_id, +Error **errp);int qcow2_snapshot_delete (BlockDriverState *bs,const char *snapshot_id);int qcow2_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab);int qcow2_snapshot_load_tmp (BlockDriverState *bs,const char *snapshot_name);block/rbd.c +0
-1@@ -867,12 +867,16 @@ static int qemu_rbd_snap_remove(BlockDriverState *bs, } static int qemu_rbd_snap_rollback(BlockDriverState *bs, -const char *snapshot_name)
block/rbd.c static int qemu_rbd_snap_remove(BlockDriverState *bs, · line 879
Quoted 10 lines
block/rbd.c +5
-0+const char *snapshot_name, + Error **errp) { BDRVRBDState *s = bs->opaque;int r; r =rbd_snap_rollback (s->image, snapshot_name); +if (r <0 ) { +error_set (errp,QERR_GENERIC_ERROR , r); + }
The Right Thing to do here is to add an Error argument to rbd_snap_rollback(), as it knows the error cause. An alternative could be to do something like:
error_setg(errp, "can't roll back: %s\n", strerror(-r));
This could even be done by the higher layers. As I said above, I think it's better to discuss with the block layer guys first how the block layer should be "qapimized".
Quoted 96 lines
block/rbd.c +0
-0return r; }block/sheepdog.c +9
-7@@ -1799,7 +1799,9 @@ cleanup:return ret; } -static int sd_snapshot_goto (BlockDriverState *bs,const char *snapshot_id) +static int sd_snapshot_goto (BlockDriverState *bs, +const char *snapshot_id, +Error **errp) {BDRVSheepdogState *s = bs->opaque;BDRVSheepdogState *old_s;@@ -1824,13 +1826,12 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id) ret =find_vdi_name (s, vdi, snapid, tag, &vid,1 );if (ret) { -error_report ("Failed to find_vdi_name" ); +error_set (errp,QERR_OPEN_FILE_FAILED , vdi); goto out; } fd =connect_to_sdog (s->addr, s->port);if (fd <0 ) { -error_report ("failed to connect" ); ret = fd; goto out; }@@ -1848,7 +1849,8 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)memcpy (&s->inode, buf,sizeof (s->inode));if (!s->inode.vm_state_size) { -error_report ("Invalid snapshot" ); +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"existing snapshot" ); ret = -ENOENT ; goto out; }@@ -1864,9 +1866,9 @@ out:memcpy (s, old_s,sizeof (BDRVSheepdogState));g_free (buf);g_free (old_s); - -error_report ("failed to open. recover old bdrv_sd_state." ); - +if (!error_is_set (errp)) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; }block_int.h +2
-1@@ -209,7 +209,8 @@ struct BlockDriver { QEMUSnapshotInfo *sn_info, Error **errp);int (*bdrv_snapshot_goto)(BlockDriverState *bs, -const char *snapshot_id); +const char *snapshot_id, +Error **errp);int (*bdrv_snapshot_delete)(BlockDriverState *bs,const char *snapshot_id);int (*bdrv_snapshot_list)(BlockDriverState *bs,QEMUSnapshotInfo **psn_info);qemu-img.c +1
-1@@ -1275,7 +1275,7 @@ static int img_snapshot(int argc, char **argv)break ;case SNAPSHOT_APPLY : - ret =bdrv_snapshot_goto (bs, snapshot_name); + ret =bdrv_snapshot_goto (bs, snapshot_name,NULL );if (ret) {error_report ("Could not apply snapshot '%s': %d (%s)" , snapshot_name, ret,strerror (-ret));savevm.c +1
-1@@ -2256,7 +2256,7 @@ int load_vmstate(const char *name) bs =NULL ;while ((bs =bdrv_next (bs))) {if (bdrv_can_snapshot (bs)) { - ret =bdrv_snapshot_goto (bs, name); + ret =bdrv_snapshot_goto (bs, name,NULL );if (ret <0 ) {error_report ("Error %d while activating snapshot '%s' on '%s'" , ret, name,bdrv_get_device_name (bs));
PATCH 4/18 block: add error parameter to bdrv_snapshot_delete() and related functions
In reply to Pavel Hrdina--- block.c | 26 ++++++++++++++++++-------- block.h | 4 +++- block/qcow2-snapshot.c | 9 ++++++++- block/qcow2.h | 4 +++- block/rbd.c | 6 +++++- block/sheepdog.c | 4 +++- block_int.h | 4 +++- qemu-img.c | 2 +- savevm.c | 4 ++-- 9 files changed, 46 insertions(+), 17 deletions(-)
block.c +18 -8
@@ -2712,16 +2712,26 @@ int bdrv_snapshot_goto(BlockDriverState *bs,return ret; } -int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id) +int bdrv_snapshot_delete (BlockDriverState *bs, +const char *snapshot_id, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv) -return -ENOMEDIUM ; -if (drv->bdrv_snapshot_delete) -return drv->bdrv_snapshot_delete (bs, snapshot_id); -if (bs->file) -return bdrv_snapshot_delete (bs->file, snapshot_id); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs)); + ret = -ENOMEDIUM ; + }else if (drv->bdrv_snapshot_delete) { + ret = drv->bdrv_snapshot_delete (bs, snapshot_id, errp); + }else if (bs->file) { + ret =bdrv_snapshot_delete (bs->file, snapshot_id, errp); + }else { +error_set (errp,QERR_NOT_SUPPORTED ); + ret = -ENOTSUP ; + } + +return ret; } int bdrv_snapshot_list(BlockDriverState *bs,
block.h +3 -1
@@ -301,7 +301,9 @@ int bdrv_snapshot_create(BlockDriverState *bs,int bdrv_snapshot_goto (BlockDriverState *bs,const char *snapshot_id,Error **errp); -int bdrv_snapshot_delete (BlockDriverState *bs,const char *snapshot_id); +int bdrv_snapshot_delete (BlockDriverState *bs, +const char *snapshot_id, +Error **errp);int bdrv_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_info); int bdrv_snapshot_load_tmp(BlockDriverState *bs,
block/qcow2-snapshot.c +8 -1
@@ -544,7 +544,9 @@ fail:return ret; } -int qcow2_snapshot_delete (BlockDriverState *bs,const char *snapshot_id) +int qcow2_snapshot_delete (BlockDriverState *bs, +const char *snapshot_id, +Error **errp) {BDRVQcowState *s = bs->opaque;QCowSnapshot sn;
@@ -553,6 +555,8 @@ int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)/* Search the snapshot */ snapshot_index =find_snapshot_by_id_or_name (bs, snapshot_id);if (snapshot_index <0 ) { +error_set (errp,QERR_INVALID_PARAMETER_VALUE , +"name" ,"existing snapshot id or tag" );return -ENOENT ; } sn = s->snapshots[snapshot_index];
@@ -564,6 +568,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) s->nb_snapshots--; ret =qcow2_write_snapshots (bs);if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret);return ret; }
@@ -581,6 +586,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id) ret =qcow2_update_snapshot_refcount (bs, sn.l1_table_offset, sn.l1_size,-1 );if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret);return ret; }qcow2_free_clusters (bs, sn.l1_table_offset, sn.l1_size *sizeof (uint64_t ));
@@ -588,6 +594,7 @@ int qcow2_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)/* must update the copied flag on the current cluster offsets */ ret =qcow2_update_snapshot_refcount (bs, s->l1_table_offset, s->l1_size,0 );if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret);return ret; }
block/qcow2.h +3 -1
@@ -314,7 +314,9 @@ int qcow2_snapshot_create(BlockDriverState *bs,int qcow2_snapshot_goto (BlockDriverState *bs,const char *snapshot_id,Error **errp); -int qcow2_snapshot_delete (BlockDriverState *bs,const char *snapshot_id); +int qcow2_snapshot_delete (BlockDriverState *bs, +const char *snapshot_id, +Error **errp);int qcow2_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab);int qcow2_snapshot_load_tmp (BlockDriverState *bs,const char *snapshot_name);
block/rbd.c +5 -1
@@ -857,12 +857,16 @@ static int qemu_rbd_snap_create(BlockDriverState *bs, }static int qemu_rbd_snap_remove (BlockDriverState *bs, -const char *snapshot_name) +const char *snapshot_name, +Error **errp) {BDRVRBDState *s = bs->opaque;int r; r =rbd_snap_remove (s->image, snapshot_name); +if (r <0 ) { +error_set (errp,QERR_GENERIC_ERROR , r); + }return r; }
block/sheepdog.c +3 -1
@@ -1872,7 +1872,9 @@ out:return ret; } -static int sd_snapshot_delete (BlockDriverState *bs,const char *snapshot_id) +static int sd_snapshot_delete (BlockDriverState *bs, +const char *snapshot_id, +Error **errp) {/* FIXME: Delete specified snapshot id. */ return 0 ;
block_int.h +3 -1
@@ -211,7 +211,9 @@ struct BlockDriver {int (*bdrv_snapshot_goto)(BlockDriverState *bs,const char *snapshot_id,Error **errp); -int (*bdrv_snapshot_delete)(BlockDriverState *bs,const char *snapshot_id); +int (*bdrv_snapshot_delete)(BlockDriverState *bs, +const char *snapshot_id, +Error **errp);int (*bdrv_snapshot_list)(BlockDriverState *bs,QEMUSnapshotInfo **psn_info); int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs,
qemu-img.c +1 -1
@@ -1283,7 +1283,7 @@ static int img_snapshot(int argc, char **argv)break ;case SNAPSHOT_DELETE : - ret =bdrv_snapshot_delete (bs, snapshot_name); + ret =bdrv_snapshot_delete (bs, snapshot_name,NULL );if (ret) {error_report ("Could not delete snapshot '%s': %d (%s)" , snapshot_name, ret,strerror (-ret));
savevm.c +2 -2
@@ -2051,7 +2051,7 @@ static int del_existing_snapshots(Monitor *mon, const char *name)if (bdrv_can_snapshot (bs) &&bdrv_snapshot_find (bs, snapshot, name) >=0 ) { - ret =bdrv_snapshot_delete (bs, name); + ret =bdrv_snapshot_delete (bs, name,NULL );if (ret <0 ) { monitor_printf(mon, "Error while deleting snapshot on '%s'\n",
@@ -2299,7 +2299,7 @@ void do_delvm(Monitor *mon, const QDict *qdict) bs1 =NULL ;while ((bs1 =bdrv_next (bs1))) {if (bdrv_can_snapshot (bs1)) { - ret =bdrv_snapshot_delete (bs1, name); + ret =bdrv_snapshot_delete (bs1, name,NULL );if (ret <0 ) {if (ret == -ENOTSUP ) monitor_printf(mon,
Signature · 1 line
1.7.11.2
PATCH 5/18 block: add error parameter to bdrv_snapshot_list() and related functions
In reply to Pavel Hrdina--- block.c | 25 +++++++++++++++++-------- block.h | 3 ++- block/qcow2-snapshot.c | 4 +++- block/qcow2.h | 4 +++- block/rbd.c | 4 +++- block/sheepdog.c | 11 +++++++++-- block_int.h | 3 ++- qemu-img.c | 2 +- savevm.c | 4 ++-- 9 files changed, 42 insertions(+), 18 deletions(-)
block.c +17 -8
@@ -2735,16 +2735,25 @@ int bdrv_snapshot_delete(BlockDriverState *bs, }int bdrv_snapshot_list (BlockDriverState *bs, -QEMUSnapshotInfo **psn_info) +QEMUSnapshotInfo **psn_info, +Error **errp) {BlockDriver *drv = bs->drv; -if (!drv) -return -ENOMEDIUM ; -if (drv->bdrv_snapshot_list) -return drv->bdrv_snapshot_list (bs, psn_info); -if (bs->file) -return bdrv_snapshot_list (bs->file, psn_info); -return -ENOTSUP ; +int ret; + +if (!drv) { +error_set (errp,QERR_DEVICE_HAS_NO_MEDIUM ,bdrv_get_device_name (bs)); + ret = -ENOMEDIUM ; + }else if (drv->bdrv_snapshot_list) { + ret = drv->bdrv_snapshot_list (bs, psn_info, errp); + }else if (bs->file) { + ret =bdrv_snapshot_list (bs->file, psn_info, errp); + }else { +error_set (errp,QERR_NOT_SUPPORTED ); + ret = -ENOTSUP ; + } + +return ret; } int bdrv_snapshot_load_tmp(BlockDriverState *bs,
block.h +2 -1
@@ -305,7 +305,8 @@ int bdrv_snapshot_delete(BlockDriverState *bs,const char *snapshot_id, Error **errp);int bdrv_snapshot_list (BlockDriverState *bs, -QEMUSnapshotInfo **psn_info); +QEMUSnapshotInfo **psn_info, +Error **errp);int bdrv_snapshot_load_tmp (BlockDriverState *bs,const char *snapshot_name);char *bdrv_snapshot_dump (char *buf,int buf_size,QEMUSnapshotInfo *sn);
block/qcow2-snapshot.c +3 -1
@@ -607,7 +607,9 @@ int qcow2_snapshot_delete(BlockDriverState *bs,return 0 ; } -int qcow2_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab) +int qcow2_snapshot_list (BlockDriverState *bs, +QEMUSnapshotInfo **psn_tab, +Error **errp) {BDRVQcowState *s = bs->opaque;QEMUSnapshotInfo *sn_tab, *sn_info;
block/qcow2.h +3 -1
@@ -317,7 +317,9 @@ int qcow2_snapshot_goto(BlockDriverState *bs,int qcow2_snapshot_delete (BlockDriverState *bs,const char *snapshot_id,Error **errp); -int qcow2_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab); +int qcow2_snapshot_list (BlockDriverState *bs, +QEMUSnapshotInfo **psn_tab, +Error **errp);int qcow2_snapshot_load_tmp (BlockDriverState *bs,const char *snapshot_name);void qcow2_free_snapshots (BlockDriverState *bs);
block/rbd.c +3 -1
@@ -885,7 +885,8 @@ static int qemu_rbd_snap_rollback(BlockDriverState *bs, }static int qemu_rbd_snap_list (BlockDriverState *bs, -QEMUSnapshotInfo **psn_tab) +QEMUSnapshotInfo **psn_tab, +Error **errp) {BDRVRBDState *s = bs->opaque;QEMUSnapshotInfo *sn_info, *sn_tab =NULL ;
@@ -902,6 +903,7 @@ static int qemu_rbd_snap_list(BlockDriverState *bs, }while (snap_count == -ERANGE );if (snap_count <=0 ) { +error_set (errp,QERR_OPEN_FILE_FAILED ,bdrv_get_device_name (bs)); goto done; }
block/sheepdog.c +9 -2
@@ -1880,7 +1880,9 @@ static int sd_snapshot_delete(BlockDriverState *bs,return 0 ; } -static int sd_snapshot_list (BlockDriverState *bs,QEMUSnapshotInfo **psn_tab) +static int sd_snapshot_list (BlockDriverState *bs, +QEMUSnapshotInfo **psn_tab, +Error **errp) {BDRVSheepdogState *s = bs->opaque;SheepdogReq req;
@@ -1898,6 +1900,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) fd =connect_to_sdog (s->addr, s->port);if (fd <0 ) { +error_set (errp,QERR_GENERIC_ERROR , fd); ret = fd; goto out; }
@@ -1914,6 +1917,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)closesocket (fd);if (ret) { +error_set (errp,QERR_GENERIC_ERROR , ret); goto out; }
@@ -1925,7 +1929,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab) fd =connect_to_sdog (s->addr, s->port);if (fd <0 ) { -error_report ("failed to connect" ); +error_set (errp,QERR_GENERIC_ERROR , fd); ret = fd; goto out; }
@@ -1965,6 +1969,9 @@ out:g_free (vdi_inuse);if (ret <0 ) { +if (!error_is_set (errp)) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; }
block_int.h +2 -1
@@ -215,7 +215,8 @@ struct BlockDriver {const char *snapshot_id, Error **errp);int (*bdrv_snapshot_list)(BlockDriverState *bs, -QEMUSnapshotInfo **psn_info); +QEMUSnapshotInfo **psn_info, +Error **errp);int (*bdrv_snapshot_load_tmp)(BlockDriverState *bs,const char *snapshot_name);int (*bdrv_get_info)(BlockDriverState *bs,BlockDriverInfo *bdi);
qemu-img.c +1 -1
@@ -1090,7 +1090,7 @@ static void dump_snapshots(BlockDriverState *bs)int nb_sns, i;char buf[256 ]; - nb_sns =bdrv_snapshot_list (bs, &sn_tab); + nb_sns =bdrv_snapshot_list (bs, &sn_tab,NULL );if (nb_sns <=0 )return ;printf ("Snapshot list:\n" );
savevm.c +2 -2
@@ -2022,7 +2022,7 @@ static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,int nb_sns, i, ret; ret = -ENOENT ; - nb_sns =bdrv_snapshot_list (bs, &sn_tab); + nb_sns =bdrv_snapshot_list (bs, &sn_tab,NULL );if (nb_sns <0 )return ret;for (i =0 ; i < nb_sns; i++) {
@@ -2328,7 +2328,7 @@ void do_info_snapshots(Monitor *mon)return ; } - nb_sns =bdrv_snapshot_list (bs, &sn_tab); + nb_sns =bdrv_snapshot_list (bs, &sn_tab,NULL );if (nb_sns <0 ) {monitor_printf (mon,"bdrv_snapshot_list: error %d\n" , nb_sns);return ;
Signature · 1 line
1.7.11.2
PATCH 6/18 block: add error parameter to bdrv_snapshot_find()
In reply to Pavel Hrdina--- savevm.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
savevm.c +18 -10
@@ -2015,16 +2015,21 @@ out:return ret; } -static int bdrv_snapshot_find (BlockDriverState *bs,QEMUSnapshotInfo *sn_info, -const char *name) +static int bdrv_snapshot_find (BlockDriverState *bs, +QEMUSnapshotInfo *sn_info, +const char *name, +Error **errp) {QEMUSnapshotInfo *sn_tab, *sn;int nb_sns, i, ret; + + nb_sns =bdrv_snapshot_list (bs, &sn_tab, errp); +if (error_is_set (errp)) { +return nb_sns; + } + ret = -ENOENT ; - nb_sns =bdrv_snapshot_list (bs, &sn_tab,NULL ); -if (nb_sns <0 ) -return ret;for (i =0 ; i < nb_sns; i++) { sn = &sn_tab[i];if (!strcmp (sn->id_str, name) || !strcmp (sn->name, name)) {
@@ -2034,6 +2039,9 @@ static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, } }g_free (sn_tab); +if (ret <0 ) { +error_set (errp,QERR_OPEN_FILE_FAILED , name); + }return ret; }
@@ -2049,7 +2057,7 @@ static int del_existing_snapshots(Monitor *mon, const char *name) bs =NULL ;while ((bs =bdrv_next (bs))) {if (bdrv_can_snapshot (bs) && -bdrv_snapshot_find (bs, snapshot, name) >=0 ) +bdrv_snapshot_find (bs, snapshot, name,NULL ) >=0 ) { ret =bdrv_snapshot_delete (bs, name,NULL );if (ret <0 ) {
@@ -2120,7 +2128,7 @@ void do_savevm(Monitor *mon, const QDict *qdict) sn->vm_clock_nsec =qemu_get_clock_ns (vm_clock);if (name) { - ret =bdrv_snapshot_find (bs, old_sn, name); + ret =bdrv_snapshot_find (bs, old_sn, name,NULL );if (ret >=0 ) {pstrcpy (sn->name,sizeof (sn->name), old_sn->name);pstrcpy (sn->id_str,sizeof (sn->id_str), old_sn->id_str);
@@ -2218,7 +2226,7 @@ int load_vmstate(const char *name) }/* Don't even try to load empty VM states */ - ret =bdrv_snapshot_find (bs_vm_state, &sn, name); + ret =bdrv_snapshot_find (bs_vm_state, &sn, name,NULL );if (ret <0 ) {return ret; }else if (sn.vm_state_size ==0 ) {
@@ -2242,7 +2250,7 @@ int load_vmstate(const char *name)return -ENOTSUP ; } - ret =bdrv_snapshot_find (bs, &sn, name); + ret =bdrv_snapshot_find (bs, &sn, name,NULL );if (ret <0 ) {error_report ("Device '%s' does not have the requested snapshot '%s'" ,bdrv_get_device_name (bs), name);
@@ -2348,7 +2356,7 @@ void do_info_snapshots(Monitor *mon)while ((bs1 =bdrv_next (bs1))) {if (bdrv_can_snapshot (bs1) && bs1 != bs) { - ret =bdrv_snapshot_find (bs1, sn_info, sn->id_str); + ret =bdrv_snapshot_find (bs1, sn_info, sn->id_str,NULL );if (ret <0 ) { available =0 ;break ;
Signature · 1 line
1.7.11.2
PATCH 7/18 block: add error parameter to del_existing_snapshots()
In reply to Pavel Hrdina--- savevm.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
savevm.c +4 -8
@@ -2048,22 +2048,18 @@ static int bdrv_snapshot_find(BlockDriverState *bs,/* * Deletes snapshots of a given name in all opened images. */ -static int del_existing_snapshots (Monitor *mon,const char *name) +static int del_existing_snapshots (const char *name, +Error **errp) {BlockDriverState *bs;QEMUSnapshotInfo sn1, *snapshot = &sn1; -int ret; bs =NULL ;while ((bs =bdrv_next (bs))) {if (bdrv_can_snapshot (bs) &&bdrv_snapshot_find (bs, snapshot, name,NULL ) >=0 ) { - ret =bdrv_snapshot_delete (bs, name,NULL ); -if (ret <0 ) { -monitor_printf (mon, -"Error while deleting snapshot on '%s'\n" , -bdrv_get_device_name (bs)); +if (bdrv_snapshot_delete (bs, name, errp) <0 ) {return -1 ; } }
@@ -2148,7 +2144,7 @@ void do_savevm(Monitor *mon, const QDict *qdict) }/* Delete old snapshots of the same name */ -if (name &&del_existing_snapshots (mon, name) <0 ) { +if (name &&del_existing_snapshots (name,NULL ) <0 ) { goto the_end; }
Signature · 1 line
1.7.11.2
PATCH 8/18 savevm: add error parameter to qemu_savevm_state_begin()
In reply to Pavel Hrdina--- migration.c | 2 +- savevm.c | 7 +++++-- sysemu.h | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-)
migration.c +1 -1
@@ -429,7 +429,7 @@ void migrate_fd_connect(MigrationState *s) migrate_fd_close);DPRINTF ("beginning savevm\n" ); - ret =qemu_savevm_state_begin (s->file, &s->params); + ret =qemu_savevm_state_begin (s->file, &s->params,NULL );if (ret <0 ) {DPRINTF ("failed, %d\n" , ret);migrate_fd_error (s);
savevm.c +5 -2
@@ -1555,7 +1555,8 @@ bool qemu_savevm_state_blocked(Error **errp) }int qemu_savevm_state_begin (QEMUFile *f, -const MigrationParams *params) +const MigrationParams *params, +Error **errp) {SaveStateEntry *se;int ret;
@@ -1595,12 +1596,14 @@ int qemu_savevm_state_begin(QEMUFile *f, ret = se->ops->save_live_setup (f, se->opaque);if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret);qemu_savevm_state_cancel (f);return ret; } } ret =qemu_file_get_error (f);if (ret !=0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret);qemu_savevm_state_cancel (f); }
@@ -1737,7 +1740,7 @@ static int qemu_savevm_state(QEMUFile *f) goto out; } - ret =qemu_savevm_state_begin (f, ¶ms); + ret =qemu_savevm_state_begin (f, ¶ms,NULL );if (ret <0 ) goto out;
sysemu.h +2 -1
@@ -78,7 +78,8 @@ void qemu_announce_self(void);bool qemu_savevm_state_blocked (Error **errp);int qemu_savevm_state_begin (QEMUFile *f, -const MigrationParams *params); +const MigrationParams *params, +Error **errp);int qemu_savevm_state_iterate (QEMUFile *f);int qemu_savevm_state_complete (QEMUFile *f);void qemu_savevm_state_cancel (QEMUFile *f);
Signature · 1 line
1.7.11.2
PATCH 9/18 savevm: add error parameter to qemu_savevm_state_iterate()
In reply to Pavel Hrdina--- migration.c | 2 +- savevm.c | 11 +++++++++-- sysemu.h | 3 ++- 3 files changed, 12 insertions(+), 4 deletions(-)
migration.c +1 -1
@@ -321,7 +321,7 @@ static void migrate_fd_put_ready(void *opaque) }DPRINTF ("iterate\n" ); - ret =qemu_savevm_state_iterate (s->file); + ret =qemu_savevm_state_iterate (s->file,NULL );if (ret <0 ) {migrate_fd_error (s); }else if (ret ==1 ) {
savevm.c +9 -2
@@ -1617,7 +1617,8 @@ int qemu_savevm_state_begin(QEMUFile *f,* 0 : We haven't finished, caller have to go again * 1 : We have finished, we can go to complete phase */ -int qemu_savevm_state_iterate (QEMUFile *f) +int qemu_savevm_state_iterate (QEMUFile *f, +Error **errp) {SaveStateEntry *se;int ret =1 ;
@@ -1651,10 +1652,16 @@ int qemu_savevm_state_iterate(QEMUFile *f) } }if (ret !=0 ) { +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }return ret; } ret =qemu_file_get_error (f);if (ret !=0 ) { +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); + }qemu_savevm_state_cancel (f); }return ret;
@@ -1745,7 +1752,7 @@ static int qemu_savevm_state(QEMUFile *f) goto out;do { - ret =qemu_savevm_state_iterate (f); + ret =qemu_savevm_state_iterate (f,NULL );if (ret <0 ) goto out; }while (ret ==0 );
sysemu.h +2 -1
@@ -80,7 +80,8 @@ bool qemu_savevm_state_blocked(Error **errp);int qemu_savevm_state_begin (QEMUFile *f,const MigrationParams *params,Error **errp); -int qemu_savevm_state_iterate (QEMUFile *f); +int qemu_savevm_state_iterate (QEMUFile *f, +Error **errp);int qemu_savevm_state_complete (QEMUFile *f);void qemu_savevm_state_cancel (QEMUFile *f);int qemu_loadvm_state (QEMUFile *f);
Signature · 1 line
1.7.11.2
PATCH 10/18 savevm: add error parameter to qemu_savevm_state_complete()
In reply to Pavel Hrdina--- migration.c | 2 +- savevm.c | 13 ++++++++++--- sysemu.h | 3 ++- 3 files changed, 13 insertions(+), 5 deletions(-)
migration.c +1 -1
@@ -331,7 +331,7 @@ static void migrate_fd_put_ready(void *opaque)qemu_system_wakeup_request (QEMU_WAKEUP_REASON_OTHER );vm_stop_force_state (RUN_STATE_FINISH_MIGRATE ); -if (qemu_savevm_state_complete (s->file) <0 ) { +if (qemu_savevm_state_complete (s->file,NULL ) <0 ) {migrate_fd_error (s); }else {migrate_fd_completed (s);
savevm.c +10 -3
@@ -1667,7 +1667,8 @@ int qemu_savevm_state_iterate(QEMUFile *f,return ret; } -int qemu_savevm_state_complete (QEMUFile *f) +int qemu_savevm_state_complete (QEMUFile *f, +Error **errp) {SaveStateEntry *se;int ret;
@@ -1691,6 +1692,7 @@ int qemu_savevm_state_complete(QEMUFile *f) ret = se->ops->save_live_complete (f, se->opaque);trace_savevm_section_end (se->section_id);if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret);return ret; } }
@@ -1720,7 +1722,12 @@ int qemu_savevm_state_complete(QEMUFile *f)qemu_put_byte (f,QEMU_VM_EOF ); -return qemu_file_get_error (f); + ret =qemu_file_get_error (f); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); + } + +return ret; }void qemu_savevm_state_cancel (QEMUFile *f)
@@ -1757,7 +1764,7 @@ static int qemu_savevm_state(QEMUFile *f) goto out; }while (ret ==0 ); - ret =qemu_savevm_state_complete (f); + ret =qemu_savevm_state_complete (f,NULL ); out:if (ret ==0 ) {
sysemu.h +2 -1
@@ -82,7 +82,8 @@ int qemu_savevm_state_begin(QEMUFile *f, Error **errp);int qemu_savevm_state_iterate (QEMUFile *f,Error **errp); -int qemu_savevm_state_complete (QEMUFile *f); +int qemu_savevm_state_complete (QEMUFile *f, +Error **errp);void qemu_savevm_state_cancel (QEMUFile *f);int qemu_loadvm_state (QEMUFile *f);
Signature · 1 line
1.7.11.2
PATCH 11/18 savevm: add error parameter to qemu_savevm_state()
In reply to Pavel Hrdina--- savevm.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
savevm.c +11 -8
@@ -1741,7 +1741,8 @@ void qemu_savevm_state_cancel(QEMUFile *f) } } -static int qemu_savevm_state (QEMUFile *f) +static int qemu_savevm_state (QEMUFile *f, +Error **errp) {int ret;MigrationParams params = {
@@ -1749,22 +1750,24 @@ static int qemu_savevm_state(QEMUFile *f) .shared = 0 }; -if (qemu_savevm_state_blocked (NULL )) { +if (qemu_savevm_state_blocked (errp)) { ret = -EINVAL ; goto out; } - ret =qemu_savevm_state_begin (f, ¶ms,NULL ); -if (ret <0 ) + ret =qemu_savevm_state_begin (f, ¶ms, errp); +if (ret <0 ) { goto out; + }do { - ret =qemu_savevm_state_iterate (f,NULL ); -if (ret <0 ) + ret =qemu_savevm_state_iterate (f, errp); +if (ret <0 ) { goto out; + } }while (ret ==0 ); - ret =qemu_savevm_state_complete (f,NULL ); + ret =qemu_savevm_state_complete (f, errp); out:if (ret ==0 ) {
@@ -2171,7 +2174,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)monitor_printf (mon,"Could not open VM state file\n" ); goto the_end; } - ret =qemu_savevm_state (f); + ret =qemu_savevm_state (f,NULL ); vm_state_size =qemu_ftell (f);qemu_fclose (f);if (ret <0 ) {
Signature · 1 line
1.7.11.2
PATCH 12/18 savevm: add error parameter to qemu_loadvm_state()
In reply to Pavel Hrdina--- migration.c | 2 +- savevm.c | 44 ++++++++++++++++++++++++++++---------------- sysemu.h | 3 ++- 3 files changed, 31 insertions(+), 18 deletions(-)
migration.c +1 -1
@@ -88,7 +88,7 @@ int qemu_start_incoming_migration(const char *uri, Error **errp)void process_incoming_migration (QEMUFile *f) { -if (qemu_loadvm_state (f) <0 ) { +if (qemu_loadvm_state (f,NULL ) <0 ) {fprintf (stderr,"load of migration failed\n" );exit (0 ); }
savevm.c +28 -16
112 lines not on this page · raw message
sysemu.h +2 -1
@@ -85,7 +85,8 @@ int qemu_savevm_state_iterate(QEMUFile *f,int qemu_savevm_state_complete (QEMUFile *f,Error **errp);void qemu_savevm_state_cancel (QEMUFile *f); -int qemu_loadvm_state (QEMUFile *f); +int qemu_loadvm_state (QEMUFile *f, +Error **errp);/* SLIRP */ void do_info_slirp (Monitor *mon);
Signature · 1 line
1.7.11.2
Re: [Qemu-devel] [PATCH 12/18] savevm: add error parameter to qemu_loadvm_state()
Quoted 99 lines · On Wed, 15 Aug 2012 09:41:53 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- migration.c | 2 +- savevm.c | 44 ++++++++++++++++++++++++++++---------------- sysemu.h | 3 ++- 3 files changed, 31 insertions(+), 18 deletions(-)migration.c +1
-1@@ -88,7 +88,7 @@ int qemu_start_incoming_migration(const char *uri, Error **errp)void process_incoming_migration (QEMUFile *f) { -if (qemu_loadvm_state (f) <0 ) { +if (qemu_loadvm_state (f,NULL ) <0 ) {fprintf (stderr,"load of migration failed\n" );exit (0 ); }savevm.c +19
-11@@ -1916,7 +1916,8 @@ typedef struct LoadStateEntry {int version_id; } LoadStateEntry; -int qemu_loadvm_state (QEMUFile *f) +int qemu_loadvm_state (QEMUFile *f, +Error **errp) { QLIST_HEAD(, LoadStateEntry) loadvm_handlers =QLIST_HEAD_INITIALIZER (loadvm_handlers);@@ -1925,21 +1926,26 @@ int qemu_loadvm_state(QEMUFile *f)unsigned int v;int ret; -if (qemu_savevm_state_blocked (NULL )) { -return -EINVAL ; +if (qemu_savevm_state_blocked (errp)) { +return -ENOTSUP ; } v =qemu_get_be32 (f); -if (v !=QEMU_VM_FILE_MAGIC ) +if (v !=QEMU_VM_FILE_MAGIC ) { +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"Unknown vm-state file magic" );return -EINVAL ; + } v =qemu_get_be32 (f);if (v ==QEMU_VM_FILE_VERSION_COMPAT ) { -fprintf (stderr,"SaveVM v2 format is obsolete and don't work anymore\n" ); +error_set (errp,QERR_NOT_SUPPORTED );return -ENOTSUP ; } -if (v !=QEMU_VM_FILE_VERSION ) +if (v !=QEMU_VM_FILE_VERSION ) { +error_set (errp,QERR_NOT_SUPPORTED );return -ENOTSUP ; + }while ((section_type =qemu_get_byte (f)) !=QEMU_VM_EOF ) {uint32_t instance_id, version_id, section_id;@@ -1961,15 +1967,18 @@ int qemu_loadvm_state(QEMUFile *f)/* Find savevm section */ se =find_se (idstr, instance_id);if (se ==NULL ) { -fprintf (stderr,"Unknown savevm section or instance '%s' %d\n" , idstr, instance_id); +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"Unknown savevm section or instance '%s' %d" , + idstr, instance_id); ret = -EINVAL ; goto out; }/* Validate version */ if (version_id > se->version_id) { -fprintf (stderr,"savevm: unsupported version %d for '%s' v%d\n" , - version_id, idstr, se->version_id); +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"savevm: unsupported version %d for '%s' v%d" , + version_id, idstr, se->version_id); ret = -EINVAL ; goto out; }@@ -1984,8 +1993,7 @@ int qemu_loadvm_state(QEMUFile *f) ret =vmstate_load (f, le->se, le->version_id);if (ret <0 ) { -fprintf (stderr,"qemu: warning: error while loading state for instance 0x%x of device '%s'\n" , - instance_id, idstr); +error_set (errp,QERR_GENERIC_ERROR , ret); goto out; }break ;
savevm.c int qemu_loadvm_state(QEMUFile *f) · line 2011
Quoted 6 lines
savevm.c +2
-1@@ -1999,20 +2007,21 @@ int qemu_loadvm_state(QEMUFile *f) } }if (le ==NULL ) { -fprintf (stderr,"Unknown savevm section %d\n" , section_id); +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"Unknown savevm section %d" , section_id);
You sure that this error message will be printed to the terminal? This has to be done by the caller.
Quoted 52 lines
savevm.c +7
-4ret = -EINVAL ; goto out; } ret =vmstate_load (f, le->se, le->version_id);if (ret <0 ) { -fprintf (stderr,"qemu: warning: error while loading state section id %d\n" , - section_id); +error_set (errp,QERR_GENERIC_ERROR , ret); goto out; }break ;default : -fprintf (stderr,"Unknown savevm section type %d\n" , section_type); +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"Unknown savevm section type %d" , section_type); ret = -EINVAL ; goto out; }@@ -2030,6 +2039,9 @@ out:if (ret ==0 ) { ret =qemu_file_get_error (f); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); + } }return ret;@@ -2297,7 +2309,7 @@ int load_vmstate(const char *name) }qemu_system_reset (VMRESET_SILENT ); - ret =qemu_loadvm_state (f); + ret =qemu_loadvm_state (f,NULL );qemu_fclose (f);if (ret <0 ) {sysemu.h +2
-1@@ -85,7 +85,8 @@ int qemu_savevm_state_iterate(QEMUFile *f,int qemu_savevm_state_complete (QEMUFile *f,Error **errp);void qemu_savevm_state_cancel (QEMUFile *f); -int qemu_loadvm_state (QEMUFile *f); +int qemu_loadvm_state (QEMUFile *f, +Error **errp);/* SLIRP */ void do_info_slirp (Monitor *mon);
Re: [Qemu-devel] [PATCH 12/18] savevm: add error parameter to qemu_loadvm_state()
Quoted 102 lines · Luiz Capitulino
Quoted 99 lines · On Wed, 15 Aug 2012 09:41:53 +0200 Pavel Hrdina <[email protected]> wrote:
Signed-off-by Pavel Hrdina <[email protected]>--- migration.c | 2 +- savevm.c | 44 ++++++++++++++++++++++++++++---------------- sysemu.h | 3 ++- 3 files changed, 31 insertions(+), 18 deletions(-)migration.c +1
-1@@ -88,7 +88,7 @@ int qemu_start_incoming_migration(const char *uri, Error **errp)void process_incoming_migration (QEMUFile *f) { -if (qemu_loadvm_state (f) <0 ) { +if (qemu_loadvm_state (f,NULL ) <0 ) {fprintf (stderr,"load of migration failed\n" );exit (0 ); }savevm.c +19
-11@@ -1916,7 +1916,8 @@ typedef struct LoadStateEntry {int version_id; } LoadStateEntry; -int qemu_loadvm_state (QEMUFile *f) +int qemu_loadvm_state (QEMUFile *f, +Error **errp) { QLIST_HEAD(, LoadStateEntry) loadvm_handlers =QLIST_HEAD_INITIALIZER (loadvm_handlers);@@ -1925,21 +1926,26 @@ int qemu_loadvm_state(QEMUFile *f)unsigned int v;int ret; -if (qemu_savevm_state_blocked (NULL )) { -return -EINVAL ; +if (qemu_savevm_state_blocked (errp)) { +return -ENOTSUP ; } v =qemu_get_be32 (f); -if (v !=QEMU_VM_FILE_MAGIC ) +if (v !=QEMU_VM_FILE_MAGIC ) { +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"Unknown vm-state file magic" );return -EINVAL ; + } v =qemu_get_be32 (f);if (v ==QEMU_VM_FILE_VERSION_COMPAT ) { -fprintf (stderr,"SaveVM v2 format is obsolete and don't work anymore\n" ); +error_set (errp,QERR_NOT_SUPPORTED );return -ENOTSUP ; } -if (v !=QEMU_VM_FILE_VERSION ) +if (v !=QEMU_VM_FILE_VERSION ) { +error_set (errp,QERR_NOT_SUPPORTED );return -ENOTSUP ; + }while ((section_type =qemu_get_byte (f)) !=QEMU_VM_EOF ) {uint32_t instance_id, version_id, section_id;@@ -1961,15 +1967,18 @@ int qemu_loadvm_state(QEMUFile *f)/* Find savevm section */ se =find_se (idstr, instance_id);if (se ==NULL ) { -fprintf (stderr,"Unknown savevm section or instance '%s' %d\n" , idstr, instance_id); +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"Unknown savevm section or instance '%s' %d" , + idstr, instance_id); ret = -EINVAL ; goto out; }/* Validate version */ if (version_id > se->version_id) { -fprintf (stderr,"savevm: unsupported version %d for '%s' v%d\n" , - version_id, idstr, se->version_id); +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"savevm: unsupported version %d for '%s' v%d" , + version_id, idstr, se->version_id); ret = -EINVAL ; goto out; }@@ -1984,8 +1993,7 @@ int qemu_loadvm_state(QEMUFile *f) ret =vmstate_load (f, le->se, le->version_id);if (ret <0 ) { -fprintf (stderr,"qemu: warning: error while loading state for instance 0x%x of device '%s'\n" , - instance_id, idstr); +error_set (errp,QERR_GENERIC_ERROR , ret); goto out; }break ;@@ -1999,20 +2007,21 @@ int qemu_loadvm_state(QEMUFile *f)
Quoted 8 lines
savevm.c int qemu_loadvm_state(QEMUFile *f) · line 2011
Quoted 6 lines
savevm.c +2
-1} }if (le ==NULL ) { -fprintf (stderr,"Unknown savevm section %d\n" , section_id); +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"Unknown savevm section %d" , section_id);You sure that this error message will be printed to the terminal? This has to be done by the caller.
While loading snapshot yes, but while migrating no. I think, that we should rewrite migration error propagation too.
Quoted 53 lines
Quoted 53 lines
savevm.c +7
-4ret = -EINVAL ; goto out; } ret =vmstate_load (f, le->se, le->version_id);if (ret <0 ) { -fprintf (stderr,"qemu: warning: error while loading state section id %d\n" , - section_id); +error_set (errp,QERR_GENERIC_ERROR , ret); goto out; }break ;default : -fprintf (stderr,"Unknown savevm section type %d\n" , section_type); +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"Unknown savevm section type %d" , section_type); ret = -EINVAL ; goto out; }@@ -2030,6 +2039,9 @@ out:if (ret ==0 ) { ret =qemu_file_get_error (f); +if (ret <0 ) { +error_set (errp,QERR_GENERIC_ERROR , ret); + } }return ret;@@ -2297,7 +2309,7 @@ int load_vmstate(const char *name) }qemu_system_reset (VMRESET_SILENT ); - ret =qemu_loadvm_state (f); + ret =qemu_loadvm_state (f,NULL );qemu_fclose (f);if (ret <0 ) {sysemu.h +2
-1@@ -85,7 +85,8 @@ int qemu_savevm_state_iterate(QEMUFile *f,int qemu_savevm_state_complete (QEMUFile *f,Error **errp);void qemu_savevm_state_cancel (QEMUFile *f); -int qemu_loadvm_state (QEMUFile *f); +int qemu_loadvm_state (QEMUFile *f, +Error **errp);/* SLIRP */ void do_info_slirp (Monitor *mon);
PATCH 13/18 qapi: Convert savevm
In reply to Pavel Hrdina--- hmp-commands.hx | 2 +- hmp.c | 10 ++++++++++ hmp.h | 1 + qapi-schema.json | 19 +++++++++++++++++++ qmp-commands.hx | 29 +++++++++++++++++++++++++++++ savevm.c | 25 +++++++++---------------- sysemu.h | 1 - 7 files changed, 69 insertions(+), 18 deletions(-)
hmp-commands.hx +1 -1
@@ -267,7 +267,7 @@ ETEXI .args_type = "name:s?", .params = "[tag|id]", .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created", - .mhandler.cmd = do_savevm, + .mhandler.cmd = hmp_vm_snapshot_save, }, STEXI
hmp.c +10 -0
@@ -1102,3 +1102,13 @@ void hmp_closefd(Monitor *mon, const QDict *qdict)qmp_closefd (fdname, &errp);hmp_handle_error (mon, &errp); } + +void hmp_vm_snapshot_save (Monitor *mon,const QDict *qdict) +{ +const char *name =qdict_get_try_str (qdict,"name" ); +Error *err =NULL ; + +qmp_vm_snapshot_save (!!name, name, &err); + +hmp_handle_error (mon, &err); +}
hmp.h +1 -0
@@ -71,5 +71,6 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict);void hmp_netdev_del (Monitor *mon,const QDict *qdict);void hmp_getfd (Monitor *mon,const QDict *qdict);void hmp_closefd (Monitor *mon,const QDict *qdict); +void hmp_vm_snapshot_save (Monitor *mon,const QDict *qdict);#endif
qapi-schema.json +19 -0
@@ -2356,3 +2356,22 @@ # Since: 1.2.0 ## { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] } + +## +# @vm-snapshot-save: +# +# Create a snapshot of the whole virtual machine. If '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. +# +# The VM is automatically stopped and resumed and saving a snapshot can take +# a long time. +# +# @name: tag or id of new or existing snapshot +# +# Returns: Nothing on success +# If an error occurs, GenericError with error message +# +# Since: 1.2 +## +{ 'command': 'vm-snapshot-save', 'data': {'*name': 'str'} }
qmp-commands.hx +29 -0
@@ -1111,6 +1111,35 @@ Example: EQMP { + .name = "vm-snapshot-save", + .args_type = "name:s?", + .params = "name", + .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created", + .mhandler.cmd_new = qmp_marshal_input_vm_snapshot_save + }, + +SQMP +vm-snapshot-save +------ + +Create a snapshot of the whole virtual machine. If '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. + +The VM is automatically stopped and resumed and saving a snapshot can take +a long time. + +Arguments: + +- "name": tag or id of new or existing snapshot + +Example: + +-> { "execute": "vm-snapshot-save", "arguments": { "name": "my_snapshot" } } +<- { "return": {} } + +EQMP + { .name = "qmp_capabilities", .args_type = "", .params = "",
savevm.c +9 -16
@@ -2100,7 +2100,7 @@ static int del_existing_snapshots(const char *name,return 0 ; } -void do_savevm (Monitor *mon,const QDict *qdict) +void qmp_vm_snapshot_save (bool has_name,const char *name,Error **errp) {BlockDriverState *bs, *bs1;QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
@@ -2115,7 +2115,6 @@ void do_savevm(Monitor *mon, const QDict *qdict)struct timeval tv;struct tm tm;#endif -const char *name =qdict_get_try_str (qdict,"name" );/* Verify if there is a device that doesn't support snapshots and is writable */ bs =NULL ;
@@ -2126,15 +2125,14 @@ void do_savevm(Monitor *mon, const QDict *qdict) }if (!bdrv_can_snapshot (bs)) { -monitor_printf (mon,"Device '%s' is writable but does not support snapshots.\n" , -bdrv_get_device_name (bs)); +error_set (errp,QERR_NOT_SUPPORTED );return ; } } bs =bdrv_snapshots ();if (!bs) { -monitor_printf (mon,"No block device can accept snapshots\n" ); +error_set (errp,QERR_NOT_SUPPORTED );return ; }
@@ -2155,7 +2153,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)#endif sn->vm_clock_nsec =qemu_get_clock_ns (vm_clock); -if (name) { +if (has_name) { ret =bdrv_snapshot_find (bs, old_sn, name,NULL );if (ret >=0 ) {pstrcpy (sn->name,sizeof (sn->name), old_sn->name);
@@ -2176,21 +2174,20 @@ void do_savevm(Monitor *mon, const QDict *qdict) }/* Delete old snapshots of the same name */ -if (name &&del_existing_snapshots (name,NULL ) <0 ) { +if (has_name &&del_existing_snapshots (name, errp) <0 ) { goto the_end; }/* save the VM state */ f =qemu_fopen_bdrv (bs,1 );if (!f) { -monitor_printf (mon,"Could not open VM state file\n" ); +error_set (errp,QERR_OPEN_FILE_FAILED ,bdrv_get_device_name (bs)); goto the_end; } - ret =qemu_savevm_state (f,NULL ); + ret =qemu_savevm_state (f, errp); vm_state_size =qemu_ftell (f);qemu_fclose (f); -if (ret <0 ) { -monitor_printf (mon,"Error %d while writing VM\n" , ret); +if (error_is_set (errp)) { goto the_end; }
@@ -2201,11 +2198,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)if (bdrv_can_snapshot (bs1)) {/* 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,NULL ); -if (ret <0 ) { -monitor_printf (mon,"Error while creating snapshot on '%s'\n" , -bdrv_get_device_name (bs1)); - } +bdrv_snapshot_create (bs1, sn, errp); } }
sysemu.h +0 -1
@@ -69,7 +69,6 @@ void qemu_remove_exit_notifier(Notifier *notify);void qemu_add_machine_init_done_notifier (Notifier *notify); -void do_savevm (Monitor *mon,const QDict *qdict);int load_vmstate (const char *name);void do_delvm (Monitor *mon,const QDict *qdict);void do_info_snapshots (Monitor *mon);
Signature · 1 line
1.7.11.2
Re: [Qemu-devel] [PATCH 13/18] qapi: Convert savevm
Quoted 2 lines · Pavel Hrdina
Signed-off-by Pavel Hrdina <[email protected]>---
I'm focusing my review more on the public interface (since that's what affects libvirt), and therefore glanced through 1 through 12 but did not pay close attention to them.
hmp.c void hmp_closefd(Monitor *mon, const QDict *qdict) · line 1108
Quoted 13 lines
hmp-commands.hx | 2 +- hmp.c | 10 ++++++++++ hmp.h | 1 + qapi-schema.json | 19 +++++++++++++++++++ qmp-commands.hx | 29 +++++++++++++++++++++++++++++ savevm.c | 25 +++++++++---------------- sysemu.h | 1 - 7 files changed, 69 insertions(+), 18 deletions(-)hmp.c +4
-0+ +void hmp_vm_snapshot_save (Monitor *mon,const QDict *qdict) +{ +const char *name =qdict_get_try_str (qdict,"name" );
In the cover letter, you said "and for QMP you have to always provide name parameter" - but this says 'name' is optional and can still be empty (id only).
qapi-schema.json line 2363
Quoted 10 lines
+++
b/qapi-schema.jsonqapi-schema.json +5
-0@@ -2356,3 +2356,22 @@ # Since: 1.2.0 ## { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] } + +## +# @vm-snapshot-save: +# +# Create a snapshot of the whole virtual machine. If 'tag' is provided,
'tag' is a misnomer, since you list @name as the parameter name.
qapi-schema.json line 2370
Quoted 7 lines
qapi-schema.json +7
-0+# it is used as human readable identifier. If there is already a snapshot +# with the same tag or ID, it is replaced. +# +# The VM is automatically stopped and resumed and saving a snapshot can take +# a long time. +# +# @name: tag or id of new or existing snapshot
Here, you document @name as required,
qapi-schema.json line 2375
Quoted 5 lines
qapi-schema.json +5
-0+# +# Returns: Nothing on success +# If an error occurs, GenericError with error message +# +# Since: 1.2
We missed 1.2 hard freeze. This better be 1.3.
Review line 2377
Quoted 2 lines
(quoted diff) +2
-0+## +{ 'command': 'vm-snapshot-save', 'data': {'*name': 'str'} }
but here, you listed it as '*name' meaning optional. I'm okay with leaving name optional, provided that it means that you end up allocating the next unique id. But if that's the case, then returning nothing is wrong; this command needs to return { 'id':'int', '*name':'str' }, so that the user knows what snapshot just got allocated.
qmp-commands.hx Example: · line 1130
Quoted 10 lines
qmp-commands.hx +10
-0+SQMP +vm-snapshot-save +------ + +Create a snapshot of the whole virtual machine. If '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. + +The VM is automatically stopped and resumed and saving a snapshot can take +a long time.
I don't like that this command can take a long time. Just today on #virt IRC, someone was complaining that 'savevm' HMP cannot be canceled.
If we're going to create a new interface, it would be nicer to create a
command that starts the save process and returns immediately, as well as commands to track progress, allow an early abort, and send an event on completion. The HMP 'savevm' interface can issue multiple QMP commands under the hood to continue with it's blocking behavior, but as long as we are fixing things, I think the QMP interface should be more powerful.
qmp-commands.hx Example: · line 1139
Quoted 9 lines
qmp-commands.hx +9
-0+ +Arguments: + +- "name": tag or id of new or existing snapshot + +Example: + +-> { "execute": "vm-snapshot-save", "arguments": { "name": "my_snapshot" } } +<- { "return": {} }
Again, you need to return the id of the just-created snapshot.
savevm.c void do_savevm(Monitor *mon, const QDict *qdict) · line 2177
Quoted 6 lines
savevm.c +1
-1@@ -2176,21 +2174,20 @@ void do_savevm(Monitor *mon, const QDict *qdict) }/* Delete old snapshots of the same name */ -if (name &&del_existing_snapshots (name,NULL ) <0 ) { +if (has_name &&del_existing_snapshots (name, errp) <0 ) {
Here's hoping later in the series updates this to make saner decisions.
(Maybe I should peruse the entire series before commenting on
individual patches?)
Signature · 2 lines
Eric Blake [email protected] +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH 13/18] qapi: Convert savevm
Quoted 16 lines · Eric Blake
Quoted 2 lines · Pavel Hrdina
Signed-off-by Pavel Hrdina<[email protected]>---
I'm focusing my review more on the public interface (since that's what affects libvirt), and therefore glanced through 1 through 12 but did not pay close attention to them.
Quoted 9 lines
hmp-commands.hx | 2 +- hmp.c | 10 ++++++++++ hmp.h | 1 + qapi-schema.json | 19 +++++++++++++++++++ qmp-commands.hx | 29 +++++++++++++++++++++++++++++ savevm.c | 25 +++++++++---------------- sysemu.h | 1 - 7 files changed, 69 insertions(+), 18 deletions(-)
Quoted 7 lines
hmp.c void hmp_closefd(Monitor *mon, const QDict *qdict) · line 1108
Quoted 4 lines
hmp.c +4
-0+ +void hmp_vm_snapshot_save (Monitor *mon,const QDict *qdict) +{ +const char *name =qdict_get_try_str (qdict,"name" );In the cover letter, you said "and for QMP you have to always provide name parameter" - but this says 'name' is optional and can still be empty (id only).
I said in cover letter that the last two patches introduce this functionality.
Quoted 28 lines
qapi-schema.json line 2363
Quoted 10 lines
+++
b/qapi-schema.jsonqapi-schema.json +5
-0@@ -2356,3 +2356,22 @@ # Since: 1.2.0 ## { 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'] } + +## +# @vm-snapshot-save: +# +# Create a snapshot of the whole virtual machine. If 'tag' is provided,'tag' is a misnomer, since you list @name as the parameter name.
qapi-schema.json line 2370
Quoted 7 lines
qapi-schema.json +7
-0+# it is used as human readable identifier. If there is already a snapshot +# with the same tag or ID, it is replaced. +# +# The VM is automatically stopped and resumed and saving a snapshot can take +# a long time. +# +# @name: tag or id of new or existing snapshotHere, you document @name as required,
qapi-schema.json line 2375
Quoted 5 lines
qapi-schema.json +5
-0+# +# Returns: Nothing on success +# If an error occurs, GenericError with error message +# +# Since: 1.2We missed 1.2 hard freeze. This better be 1.3.
Quoted 7 lines
Review line 2377
Quoted 2 lines
(quoted diff) +2
-0+## +{ 'command': 'vm-snapshot-save', 'data': {'*name': 'str'} }but here, you listed it as '*name' meaning optional. I'm okay with leaving name optional, provided that it means that you end up allocating the next unique id. But if that's the case, then returning nothing is wrong; this command needs to return { 'id':'int', '*name':'str' }, so that the user knows what snapshot just got allocated.
If you apply whole patch-series, then you have to for QMP always provide @name. As I said above, this behaviour is introduced by last two patches.
Quoted 10 lines
qmp-commands.hx Example: · line 1130
Quoted 10 lines
qmp-commands.hx +10
-0+SQMP +vm-snapshot-save +------ + +Create a snapshot of the whole virtual machine. If '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. + +The VM is automatically stopped and resumed and saving a snapshot can take +a long time.
Quoted 8 lines
I don't like that this command can take a long time. Just today on #virt IRC, someone was complaining that 'savevm' HMP cannot be canceled.
If we're going to create a new interface, it would be nicer to create a
command that starts the save process and returns immediately, as well as commands to track progress, allow an early abort, and send an event on completion. The HMP 'savevm' interface can issue multiple QMP commands under the hood to continue with it's blocking behavior, but as long as we are fixing things, I think the QMP interface should be more powerful.
Well, I could try to do it...with this I'll probably introduce new command vm-snapshot-save-cancel or vm-snaphsot-cancel as we have migrate and migrate-cancel.
Quoted 21 lines
qmp-commands.hx Example: · line 1139
Quoted 9 lines
qmp-commands.hx +9
-0+ +Arguments: + +- "name": tag or id of new or existing snapshot + +Example: + +-> { "execute": "vm-snapshot-save", "arguments": { "name": "my_snapshot" } } +<- { "return": {} }Again, you need to return the id of the just-created snapshot.
savevm.c void do_savevm(Monitor *mon, const QDict *qdict) · line 2177
Quoted 6 lines
savevm.c +1
-1@@ -2176,21 +2174,20 @@ void do_savevm(Monitor *mon, const QDict *qdict) }/* Delete old snapshots of the same name */ -if (name &&del_existing_snapshots (name,NULL ) <0 ) { +if (has_name &&del_existing_snapshots (name, errp) <0 ) {Here's hoping later in the series updates this to make saner decisions.
(Maybe I should peruse the entire series before commenting on
individual patches?)
PATCH 14/18 qapi: Convert loadvm
In reply to Pavel Hrdina--- hmp-commands.hx | 2 +- hmp.c | 10 +++++++++ hmp.h | 1 + monitor.c | 12 ----------- qapi-schema.json | 15 ++++++++++++++ qmp-commands.hx | 25 ++++++++++++++++++++++ savevm.c | 63 ++++++++++++++++++++++++++++---------------------------- sysemu.h | 1 - vl.c | 7 ++++++- 9 files changed, 90 insertions(+), 46 deletions(-)
hmp-commands.hx +1 -1
@@ -284,7 +284,7 @@ ETEXI .args_type = "name:s", .params = "tag|id", .help = "restore a VM snapshot from its tag or id", - .mhandler.cmd = do_loadvm, + .mhandler.cmd = hmp_vm_snapshot_load, }, STEXI
hmp.c +10 -0
@@ -1112,3 +1112,13 @@ void hmp_vm_snapshot_save(Monitor *mon, const QDict *qdict)hmp_handle_error (mon, &err); } + +void hmp_vm_snapshot_load (Monitor *mon,const QDict *qdict) +{ +const char *name =qdict_get_str (qdict,"name" ); +Error *err =NULL ; + +qmp_vm_snapshot_load (name, &err); + +hmp_handle_error (mon, &err); +}
hmp.h +1 -0
@@ -72,5 +72,6 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict);void hmp_getfd (Monitor *mon,const QDict *qdict);void hmp_closefd (Monitor *mon,const QDict *qdict);void hmp_vm_snapshot_save (Monitor *mon,const QDict *qdict); +void hmp_vm_snapshot_load (Monitor *mon,const QDict *qdict);#endif
monitor.c +0 -12
@@ -2330,18 +2330,6 @@ void qmp_closefd(const char *fdname, Error **errp)error_set (errp,QERR_FD_NOT_FOUND , fdname); } -static void do_loadvm (Monitor *mon,const QDict *qdict) -{ -int saved_vm_running =runstate_is_running (); -const char *name =qdict_get_str (qdict,"name" ); - -vm_stop (RUN_STATE_RESTORE_VM ); - -if (load_vmstate (name) ==0 && saved_vm_running) { -vm_start (); - } -} -int monitor_get_fd (Monitor *mon,const char *fdname) {mon_fd_t *monfd;
qapi-schema.json +15 -0
@@ -2375,3 +2375,18 @@ # Since: 1.2 ## { 'command': 'vm-snapshot-save', 'data': {'*name': 'str'} } + +## +# @vm-snapshot-load: +# +# Set the whole virtual machine to the snapshot identified by the tag +# 'tag' or the unique snapshot ID 'id'. +# +# @name: tag or id of existing snapshot +# +# Returns: Nothing on success +# If an error occurs, GenericError with error message +# +# Since: 1.2 +## +{ 'command': 'vm-snapshot-load', 'data': {'name': 'str'} }
qmp-commands.hx +25 -0
@@ -1140,6 +1140,31 @@ Example: EQMP { + .name = "vm-snapshot-load", + .args_type = "name:s", + .params = "name", + .help = "restore a VM snapshot from its tag or id", + .mhandler.cmd_new = qmp_marshal_input_vm_snapshot_load + }, + +SQMP +vm-snapshot-load +------ + +Set the whole virtual machine to the snapshot identified by the tag +'tag' or the unique snapshot ID 'id'. + +Arguments: + +- "name": tag or id of existing snapshot + +Example: + +-> { "execute": "vm-snapshot-load", "arguments": { "name": "my_snapshot" } } +<- { "return": {} } + +EQMP + { .name = "qmp_capabilities", .args_type = "", .params = "",
savevm.c +32 -31
109 lines not on this page · raw message
sysemu.h +0 -1
@@ -69,7 +69,6 @@ void qemu_remove_exit_notifier(Notifier *notify);void qemu_add_machine_init_done_notifier (Notifier *notify); -int load_vmstate (const char *name);void do_delvm (Monitor *mon,const QDict *qdict);void do_info_snapshots (Monitor *mon);
vl.c +6 -1
@@ -3683,8 +3683,13 @@ int main(int argc, char **argv, char **envp)qemu_system_reset (VMRESET_SILENT );if (loadvm) { -if (load_vmstate (loadvm) <0 ) { +Error *errp =NULL ; +qmp_vm_snapshot_load (loadvm, &errp); + +if (error_is_set (&errp)) { autostart =0 ; +error_report ("%s" ,error_get_pretty (errp)); +error_free (errp); } }
Signature · 1 line
1.7.11.2
Re: [Qemu-devel] [PATCH 14/18] qapi: Convert loadvm
Quoted 17 lines · Pavel Hrdina
Signed-off-by Pavel Hrdina <[email protected]>--- hmp-commands.hx | 2 +- hmp.c | 10 +++++++++ hmp.h | 1 + monitor.c | 12 ----------- qapi-schema.json | 15 ++++++++++++++ qmp-commands.hx | 25 ++++++++++++++++++++++ savevm.c | 63 ++++++++++++++++++++++++++++---------------------------- sysemu.h | 1 - vl.c | 7 ++++++- 9 files changed, 90 insertions(+), 46 deletions(-)qapi-schema.json +3
-0+ +## +# @vm-snapshot-load:
qapi-schema.json line 2390
Quoted 10 lines
qapi-schema.json +10
-0+# +# Set the whole virtual machine to the snapshot identified by the tag +# 'tag' or the unique snapshot ID 'id'. +# +# @name: tag or id of existing snapshot +# +# Returns: Nothing on success +# If an error occurs, GenericError with error message +# +# Since: 1.2
1.3
Signature · 2 lines
Eric Blake [email protected] +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH 14/18] qapi: Convert loadvm
Quoted 12 lines · Eric Blake
qapi-schema.json line 2388
Quoted 12 lines
qapi-schema.json +11
-0+ +## +# @vm-snapshot-load: +# +# Set the whole virtual machine to the snapshot identified by the tag +# 'tag' or the unique snapshot ID 'id'. +# +# @name: tag or id of existing snapshot +# +# Returns: Nothing on success +# If an error occurs, GenericError with error message
It might also be worth documenting that vm-snapshot-load can only load online snapshots with associated VM state (those created by savevm), and not offline snapshots (those created by 'qemu-img snapshot').
Signature · 2 lines
Eric Blake [email protected] +1-919-301-3266 Libvirt virtualization library http://libvirt.org
PATCH 15/18 qapi: Convert delvm
In reply to Pavel Hrdina--- hmp-commands.hx | 2 +- hmp.c | 10 ++++++++++ hmp.h | 1 + qapi-schema.json | 14 ++++++++++++++ qmp-commands.hx | 24 ++++++++++++++++++++++++ savevm.c | 17 +++-------------- sysemu.h | 1 - 7 files changed, 53 insertions(+), 16 deletions(-)
hmp-commands.hx +1 -1
@@ -299,7 +299,7 @@ ETEXI .args_type = "name:s", .params = "tag|id", .help = "delete a VM snapshot from its tag or id", - .mhandler.cmd = do_delvm, + .mhandler.cmd = hmp_vm_snapshot_delete, }, STEXI
hmp.c +10 -0
@@ -1122,3 +1122,13 @@ void hmp_vm_snapshot_load(Monitor *mon, const QDict *qdict)hmp_handle_error (mon, &err); } + +void hmp_vm_snapshot_delete (Monitor *mon,const QDict *qdict) +{ +const char *name =qdict_get_str (qdict,"name" ); +Error *err =NULL ; + +qmp_vm_snapshot_delete (name, &err); + +hmp_handle_error (mon, &err); +}
hmp.h +1 -0
@@ -73,5 +73,6 @@ void hmp_getfd(Monitor *mon, const QDict *qdict);void hmp_closefd (Monitor *mon,const QDict *qdict);void hmp_vm_snapshot_save (Monitor *mon,const QDict *qdict);void hmp_vm_snapshot_load (Monitor *mon,const QDict *qdict); +void hmp_vm_snapshot_delete (Monitor *mon,const QDict *qdict);#endif
qapi-schema.json +14 -0
@@ -2390,3 +2390,17 @@ # Since: 1.2 ## { 'command': 'vm-snapshot-load', 'data': {'name': 'str'} } + +## +# @vm-snapshot-delete: +# +# Delete the snapshot identified by 'tag' or 'id'. +# +# @name: tag or id of existing snapshot +# +# Returns: Nothing on success +# If an error occurs, GenericError with error message +# +# Since: 1.2 +## +{ 'command': 'vm-snapshot-delete', 'data': {'name': 'str'} }
qmp-commands.hx +24 -0
@@ -1165,6 +1165,30 @@ Example: EQMP { + .name = "vm-snapshot-delete", + .args_type = "name:s", + .params = "tag|id", + .help = "delete a VM snapshot from its tag or id", + .mhandler.cmd_new = qmp_marshal_input_vm_snapshot_delete + }, + +SQMP +vm-snapshot-delete +------ + +Delete the snapshot identified by 'tag' or 'id'. + +Arguments: + +- "name": tag or id of existing snapshot + +Example: + +-> { "execute": "vm-snapshot-delete", "arguments": { "name": "my_snapshot" } } +<- { "return": {} } + +EQMP + { .name = "qmp_capabilities", .args_type = "", .params = "",
savevm.c +3 -14
@@ -2314,31 +2314,20 @@ void qmp_vm_snapshot_load(const char *name, Error **errp) } } -void do_delvm (Monitor *mon,const QDict *qdict) +void qmp_vm_snapshot_delete (const char *name,Error **errp) {BlockDriverState *bs, *bs1; -int ret; -const char *name =qdict_get_str (qdict,"name" ); bs =bdrv_snapshots ();if (!bs) { -monitor_printf (mon,"No block device supports snapshots\n" ); +error_set (errp,QERR_NOT_SUPPORTED );return ; } bs1 =NULL ;while ((bs1 =bdrv_next (bs1))) {if (bdrv_can_snapshot (bs1)) { - ret =bdrv_snapshot_delete (bs1, name,NULL ); -if (ret <0 ) { -if (ret == -ENOTSUP ) -monitor_printf (mon, -"Snapshots not supported on device '%s'\n" , -bdrv_get_device_name (bs1)); -else -monitor_printf (mon,"Error %d while deleting snapshot on " -"'%s'\n" , ret,bdrv_get_device_name (bs1)); - } +bdrv_snapshot_delete (bs1, name, errp); } } }
sysemu.h +0 -1
@@ -69,7 +69,6 @@ void qemu_remove_exit_notifier(Notifier *notify);void qemu_add_machine_init_done_notifier (Notifier *notify); -void do_delvm (Monitor *mon,const QDict *qdict);void do_info_snapshots (Monitor *mon);void qemu_announce_self (void );
Signature · 1 line
1.7.11.2
PATCH 16/18 qapi: Convert info snapshots
In reply to Pavel Hrdina--- hmp.c | 33 +++++++++++++++++++++++++++++++++ hmp.h | 1 + monitor.c | 2 +- qapi-schema.json | 34 ++++++++++++++++++++++++++++++++++ qmp-commands.hx | 30 ++++++++++++++++++++++++++++++ savevm.c | 51 ++++++++++++++++++++++++--------------------------- sysemu.h | 2 -- 7 files changed, 123 insertions(+), 30 deletions(-)
hmp.c +33 -0
@@ -613,6 +613,39 @@ void hmp_info_block_jobs(Monitor *mon) } } +void hmp_info_snapshots (Monitor *mon) +{ +SnapshotInfoList *list; +Error *err =NULL ; +char buf[256 ]; +QEMUSnapshotInfo sn; + + list =qmp_query_vm_snapshots (&err); + +if (error_is_set (&err)) { +hmp_handle_error (mon, &err); +return ; + } + +if (!list) { +monitor_printf (mon,"There is no snapshot available.\n" ); +return ; + } +monitor_printf (mon,"%s\n" ,bdrv_snapshot_dump (buf,sizeof (buf),NULL )); +while (list) { +memcpy (&(sn.id_str), list->value->id,sizeof (sn.id_str)); +memcpy (&(sn.name), list->value->tag,sizeof (sn.name)); + sn.date_sec = list->value->date; + sn.date_nsec = sn.date_sec *1000000000 ; + sn.vm_clock_nsec = list->value->vm_clock; + sn.vm_state_size = list->value->vm_size; +monitor_printf (mon,"%s\n" ,bdrv_snapshot_dump (buf,sizeof (buf), &sn)); + list = list->next; + } + +qapi_free_SnapshotInfoList (list); +} +void hmp_quit (Monitor *mon,const QDict *qdict) {monitor_suspend (mon);
hmp.h +1 -0
@@ -36,6 +36,7 @@ void hmp_info_spice(Monitor *mon);void hmp_info_balloon (Monitor *mon);void hmp_info_pci (Monitor *mon);void hmp_info_block_jobs (Monitor *mon); +void hmp_info_snapshots (Monitor *mon);void hmp_quit (Monitor *mon,const QDict *qdict);void hmp_stop (Monitor *mon,const QDict *qdict);void hmp_system_reset (Monitor *mon,const QDict *qdict);
monitor.c +1 -1
@@ -2541,7 +2541,7 @@ static mon_cmd_t info_cmds[] = { .args_type = "", .params = "", .help = "show the currently saved VM snapshots", - .mhandler.info = do_info_snapshots, + .mhandler.info = hmp_info_snapshots, }, { .name = "status",
qapi-schema.json +34 -0
@@ -1053,6 +1053,40 @@ { 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] } ## +# @SnapshotInfo: +# +# Snapshot list. This structure contains list of snapshots for virtual machine. +# +# @id: id of the snapshot. +# +# @tag: human readable tag of the snapshot. +# +# @vm_size: size of the snapshot in Bytes. +# +# @date: date and time of the snapshot as unix timestamp. +# +# @vm_clock: time in the guest in nsecs. +# +# Since: 1.2 +## +{ 'type': 'SnapshotInfo', + 'data': {'id': 'str', 'tag': 'str', 'vm_size': 'int', + 'date': 'int', 'vm_clock': 'int'} } + +## +# @query-vm-snapshots: +# +# List available snapshots for VM. +# +# Returns: an array of @SnapshotInfo describing each snapshot or an empty array +# on success +# If an error occurs, GenericError with error message +# +# Since: 1.2 +## +{ 'command': 'query-vm-snapshots', 'returns': ['SnapshotInfo'] } + +## # @quit: # # This command will cause the QEMU process to exit gracefully. While every
qmp-commands.hx +30 -0
@@ -2465,3 +2465,33 @@ EQMP .mhandler.cmd_new = qmp_marshal_input_query_cpu_definitions, }, +SQMP +query-vm-snapshots +---------- + +List available snapshots for VM. + +Return an array of json-object, each with the following information: + +- "id": id of the snapshot. + +- "tag": human readable tag of the snapshot. + +- "vm_size": size of the snapshot in Bytes. + +- "date": date and time of the snapshot as unix timestamp. + +- "vm_clock": time in the guest in nsecs. + +Example: + +-> { "execute": "query-vm-snapshots" } +<- {"return": [{"vm_size": 212309067, "tag": "my_snapshot", + "vm_clock": 630176706190, "id": "1", "date": 1341999856}]} + +EQMP + { + .name = "query-vm-snapshots", + .args_type = "", + .mhandler.cmd_new = qmp_marshal_input_query_vm_snapshots, + },
savevm.c +24 -27
82 lines not on this page · raw message
sysemu.h +0 -2
@@ -69,8 +69,6 @@ void qemu_remove_exit_notifier(Notifier *notify);void qemu_add_machine_init_done_notifier (Notifier *notify); -void do_info_snapshots (Monitor *mon); -void qemu_announce_self (void );bool qemu_savevm_state_blocked (Error **errp);
Signature · 1 line
1.7.11.2
Re: [Qemu-devel] [PATCH 16/18] qapi: Convert info snapshots
Quoted 13 lines · Pavel Hrdina
Signed-off-by Pavel Hrdina <[email protected]>--- hmp.c | 33 +++++++++++++++++++++++++++++++++ hmp.h | 1 + monitor.c | 2 +- qapi-schema.json | 34 ++++++++++++++++++++++++++++++++++ qmp-commands.hx | 30 ++++++++++++++++++++++++++++++ savevm.c | 51 ++++++++++++++++++++++++--------------------------- sysemu.h | 2 -- 7 files changed, 123 insertions(+), 30 deletions(-)
qapi-schema.json line 1057
Quoted 5 lines
qapi-schema.json +2
-0@@ -1053,6 +1053,40 @@ { 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] } ## +# @SnapshotInfo: +#
We've got competition here:
https://lists.gnu.org/archive/html/qemu-devel/2012-08/msg02961.html
These two patches need to converge into a single design.
qapi-schema.json line 1064
Quoted 7 lines
qapi-schema.json +7
-0+# Snapshot list. This structure contains list of snapshots for virtual machine. +# +# @id: id of the snapshot. +# +# @tag: human readable tag of the snapshot. +# +# @vm_size: size of the snapshot in Bytes.
As this is a new QMP command, you should use '-', not '_'. Benoit's patch named this @vm-state-size.
qapi-schema.json line 1068
Quoted 4 lines
qapi-schema.json +4
-0+# +# @date: date and time of the snapshot as unix timestamp. +# +# @vm_clock: time in the guest in nsecs.
For online internal snapshots (those created by savevm), the vm clock offset makes sense. But for offline snapshots (those created by 'qemu-img snapshot', with no VM state), there is no vm clock offset. 'qemu-img info' lists 00:00:00.000 as a result, but I wonder if it would be better to leave this field (and vm-state-size) as #optional and omit them from the JSON for offline snapshots.
And since qemu refuses to load offline snapshots, it might be worth an additional field in the JSON that says whether a snapshot is online or offline, to make it easier for the parsing application to determine whether it can be loaded or must go through qemu-img while the guest is offline (then again, keeping vm-state-size as non-optional, and checking for 0 size, somewhat covers this).
Review line 1070
Quoted 2 lines
(quoted diff) +2
-0+# +# Since: 1.2
1.3 (entire series...)
Signature · 2 lines
Eric Blake [email protected] +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH 16/18] qapi: Convert info snapshots
Quoted 15 lines · Eric Blake
Quoted 14 lines · Pavel Hrdina
Signed-off-by Pavel Hrdina<[email protected]>--- hmp.c | 33 +++++++++++++++++++++++++++++++++ hmp.h | 1 + monitor.c | 2 +- qapi-schema.json | 34 ++++++++++++++++++++++++++++++++++ qmp-commands.hx | 30 ++++++++++++++++++++++++++++++ savevm.c | 51 ++++++++++++++++++++++++--------------------------- sysemu.h | 2 -- 7 files changed, 123 insertions(+), 30 deletions(-)qapi-schema.json +0
-0@@ -1053,6 +1053,40 @@ { 'command': 'query-block-jobs', 'returns': ['BlockJobInfo'] }
Quoted 7 lines
qapi-schema.json line 1057
Quoted 3 lines
qapi-schema.json +2
-0## +# @SnapshotInfo: +#We've got competition here:
https://lists.gnu.org/archive/html/qemu-devel/2012-08/msg02961.htmlThese two patches need to converge into a single design.
I can use his design.
Quoted 21 lines
qapi-schema.json line 1064
Quoted 7 lines
qapi-schema.json +7
-0+# Snapshot list. This structure contains list of snapshots for virtual machine. +# +# @id: id of the snapshot. +# +# @tag: human readable tag of the snapshot. +# +# @vm_size: size of the snapshot in Bytes.As this is a new QMP command, you should use '-', not '_'. Benoit's patch named this @vm-state-size.
qapi-schema.json line 1068
Quoted 4 lines
qapi-schema.json +4
-0+# +# @date: date and time of the snapshot as unix timestamp. +# +# @vm_clock: time in the guest in nsecs.For online internal snapshots (those created by savevm), the vm clock offset makes sense. But for offline snapshots (those created by 'qemu-img snapshot', with no VM state), there is no vm clock offset. 'qemu-img info' lists 00:00:00.000 as a result, but I wonder if it would be better to leave this field (and vm-state-size) as #optional and omit them from the JSON for offline snapshots.
Quoted 6 lines
And since qemu refuses to load offline snapshots, it might be worth an additional field in the JSON that says whether a snapshot is online or offline, to make it easier for the parsing application to determine whether it can be loaded or must go through qemu-img while the guest is offline (then again, keeping vm-state-size as non-optional, and checking for 0 size, somewhat covers this).
As you said, this is covered and I think that checking for 0 size is good enough.
Quoted 4 lines
Review line 1070
Quoted 2 lines
(quoted diff) +2
-0+# +# Since: 1.21.3 (entire series...)
PATCH 17/18 hmp: allow "bool" parameter to be optional
In reply to Pavel Hrdina--- monitor.c | 3 +++ 1 file changed, 3 insertions(+)
monitor.c +3 -0
@@ -3769,6 +3769,9 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon, val =1 ; }else if (p - beg ==3 && !memcmp (beg,"off" , p - beg)) { val =0 ; + }else if (*typestr =='?' ) { + typestr++; +break ; }else {monitor_printf (mon,"Expected 'on' or 'off'\n" ); goto fail;
Signature · 1 line
1.7.11.2
Re: [Qemu-devel] [PATCH 17/18] hmp: allow "bool" parameter to be optional
Quoted 4 lines · Pavel Hrdina
Signed-off-by Pavel Hrdina <[email protected]>--- monitor.c | 3 +++ 1 file changed, 3 insertions(+)
NACK. See patch 18 why I think you don't need this.
Quoted 16 lines
monitor.c +3
-0@@ -3769,6 +3769,9 @@ static const mon_cmd_t *monitor_parse_command(Monitor *mon, val =1 ; }else if (p - beg ==3 && !memcmp (beg,"off" , p - beg)) { val =0 ; + }else if (*typestr =='?' ) { + typestr++; +break ; }else {monitor_printf (mon,"Expected 'on' or 'off'\n" ); goto fail;
Signature · 2 lines
Eric Blake [email protected] +1-919-301-3266 Libvirt virtualization library http://libvirt.org
PATCH 18/18 vm-snapshot-save: add force parameter
In reply to Pavel HrdinaHMP command "savevm" now takes extra optional force parameter to specifi whether replace existing snapshot or not.
QMP command "vm-snapshot-save" has also extra optional force parameter and name parameter isn't optional anymore.
--- hmp-commands.hx | 14 +++++++------- hmp.c | 25 ++++++++++++++++++++++++- qapi-schema.json | 12 +++++++----- qmp-commands.hx | 16 +++++++++------- savevm.c | 35 ++++++++++++++--------------------- 5 files changed, 61 insertions(+), 41 deletions(-)
hmp-commands.hx +7 -7
@@ -264,19 +264,19 @@ 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 = "name:s?,force:b?", + .params = "[tag|id] [on|off]", + .help = "save a VM snapshot. To replace existing snapshot use force parameter.", .mhandler.cmd = hmp_vm_snapshot_save, }, STEXI @item savevm [@var{tag}|@var{id}] @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 -a snapshot with the same tag or ID, it is replaced. More info at -@ref{vm_snapshots}. +Create a snapshot of the whole virtual machine. Parameter "name" is optional. +If @var{tag} is provided, it is used as human readable identifier. If there is +already a snapshot with the same tag, force argument need to be "yes" to +replace it. More info at @ref{vm_snapshots}. ETEXI {
hmp.c +24 -1
@@ -1139,9 +1139,32 @@ void hmp_closefd(Monitor *mon, const QDict *qdict)void hmp_vm_snapshot_save (Monitor *mon,const QDict *qdict) {const char *name =qdict_get_try_str (qdict,"name" ); +char new_name[256 ]; +bool force =qdict_get_try_bool (qdict,"force" ,0 );Error *err =NULL ; +#ifdef _WIN32 +struct _timeb tb; +struct tm *ptm; +#else +struct timeval tv; +struct tm tm; +#endif + +if (!name) { +#ifdef _WIN32 +time_t t = tb.time; + ptm =localtime (&t); +strftime (new_name,sizeof (new_name),"vm-%Y%m%d%H%M%S" , ptm); +#else +/* cast below needed for OpenBSD where tv_sec is still 'long' */ +localtime_r ((const time_t *)&tv.tv_sec, &tm); +strftime (new_name,sizeof (new_name),"vm-%Y%m%d%H%M%S" , &tm); +#endif + }else { +pstrcpy (new_name,sizeof (new_name), name); + } -qmp_vm_snapshot_save (!!name, name, &err); +qmp_vm_snapshot_save (new_name, !!force, force, &err);hmp_handle_error (mon, &err); }
qapi-schema.json +7 -5
@@ -2394,21 +2394,23 @@ ## # @vm-snapshot-save: # -# Create a snapshot of the whole virtual machine. If '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. +# Create a snapshot of the whole virtual machine. Provided 'tag' is used as +# human readable identifier. If there is already a snapshot with the same tag, +# force argument need to be "yes" to replace it. # # The VM is automatically stopped and resumed and saving a snapshot can take # a long time. # -# @name: tag or id of new or existing snapshot +# @name: tag of new or existing snapshot +# +# @force: specify whether existing snapshot is replaced or not # # Returns: Nothing on success # If an error occurs, GenericError with error message # # Since: 1.2 ## -{ 'command': 'vm-snapshot-save', 'data': {'*name': 'str'} } +{ 'command': 'vm-snapshot-save', 'data': {'name': 'str', '*force': 'bool'} } ## # @vm-snapshot-load:
qmp-commands.hx +9 -7
@@ -1112,9 +1112,9 @@ Example: EQMP { .name = "vm-snapshot-save", - .args_type = "name:s?", - .params = "name", - .help = "save a VM snapshot. If no tag or id are provided, a new snapshot is created", + .args_type = "name:s,force:b?", + .params = "name [force]", + .help = "save a VM snapshot. To replace existing snapshot use force parameter.", .mhandler.cmd_new = qmp_marshal_input_vm_snapshot_save },
@@ -1122,16 +1122,18 @@ SQMP vm-snapshot-save ------ -Create a snapshot of the whole virtual machine. If '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. +Create a snapshot of the whole virtual machine. Provided 'tag' is used as +human readable identifier. If there is already a snapshot with the same tag, +force argument need to be "yes" to replace it. The VM is automatically stopped and resumed and saving a snapshot can take a long time. Arguments: -- "name": tag or id of new or existing snapshot +- "name": tag of new or existing snapshot + +- "force": specify whether existing snapshot is replaced or not Example:
savevm.c +14 -21
@@ -2100,7 +2100,7 @@ static int del_existing_snapshots(const char *name,return 0 ; } -void qmp_vm_snapshot_save (bool has_name,const char *name,Error **errp) +void qmp_vm_snapshot_save (const char *name,bool has_force,bool force,Error **errp) {BlockDriverState *bs, *bs1;QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
@@ -2110,10 +2110,8 @@ void qmp_vm_snapshot_save(bool has_name, const char *name, Error **errp)uint64_t vm_state_size;#ifdef _WIN32struct _timeb tb; -struct tm *ptm;#else struct timeval tv; -struct tm tm;#endif /* Verify if there is a device that doesn't support snapshots and is writable */
@@ -2153,29 +2151,24 @@ void qmp_vm_snapshot_save(bool has_name, const char *name, Error **errp)#endif sn->vm_clock_nsec =qemu_get_clock_ns (vm_clock); -if (has_name) { - ret =bdrv_snapshot_find (bs, old_sn, name,NULL ); -if (ret >=0 ) { + ret =bdrv_snapshot_find (bs, old_sn, name,NULL ); +if (ret >=0 ) { +if (has_force && force) {pstrcpy (sn->name,sizeof (sn->name), old_sn->name);pstrcpy (sn->id_str,sizeof (sn->id_str), old_sn->id_str); + +del_existing_snapshots (name, errp); +if (error_is_set (errp)) { + goto the_end; + } }else { -pstrcpy (sn->name,sizeof (sn->name), name); +error_set (errp,ERROR_CLASS_GENERIC_ERROR , +"Snapshot '%s' exist. For override specify force=yes" , + name); + goto the_end; } }else { -#ifdef _WIN32 -time_t t = tb.time; - ptm =localtime (&t); -strftime (sn->name,sizeof (sn->name),"vm-%Y%m%d%H%M%S" , ptm); -#else -/* cast below needed for OpenBSD where tv_sec is still 'long' */ -localtime_r ((const time_t *)&tv.tv_sec, &tm); -strftime (sn->name,sizeof (sn->name),"vm-%Y%m%d%H%M%S" , &tm); -#endif - } - -/* Delete old snapshots of the same name */ -if (has_name &&del_existing_snapshots (name, errp) <0 ) { - goto the_end; +pstrcpy (sn->name,sizeof (sn->name), name); }/* save the VM state */
Signature · 1 line
1.7.11.2
Re: [Qemu-devel] [PATCH 18/18] vm-snapshot-save: add force parameter
Quoted 1 line · Pavel Hrdina
HMP command "savevm" now takes extra optional force parameter to specifi whether
s/specifi/specify/
Quoted 4 lines
replace existing snapshot or not.
QMP command "vm-snapshot-save" has also extra optional force parameter and name parameter isn't optional anymore.
When HMP omits the name, what name are you using in it's place? Either a nameless snapshot is okay (and QMP must expose it), or it is an error (and HMP must now be passing a reasonable name).
/me reads patch
Oh, there was always a name; the default name was a timestamp, and you moved the timestamp creation into HMP.
hmp-commands.hx ETEXI · line 268
Quoted 10 lines
+++ b/hmp-commands.hx
hmp-commands.hx +2
-3@@ -264,19 +264,19 @@ 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 = "name:s?,force:b?", + .params = "[tag|id] [on|off]",
Rather than sticking 'force' as an optional parameter at the end, instead you want to add '-f' as a flag at the beginning.
.args_type = "force:-b,name:s?",
.params = "[-f] name"
By doing this, you no longer need 17/18.
Quoted 4 lines
hmp-commands.hx +1
-0+ .help = "save a VM snapshot. To replace existing snapshot use force parameter.", .mhandler.cmd = hmp_vm_snapshot_save, },
hmp-commands.hx ETEXI · line 278
Quoted 10 lines
hmp-commands.hx +3
-4STEXI @item savevm [@var{tag}|@var{id}] @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 -a snapshot with the same tag or ID, it is replaced. More info at -@ref{vm_snapshots}. +Create a snapshot of the whole virtual machine. Parameter "name" is optional. +If @var{tag} is provided, it is used as human readable identifier. If there is +already a snapshot with the same tag, force argument need to be "yes" to
s/force argument need/the force argument needs/
qapi-schema.json line 2399
Quoted 11 lines
qapi-schema.json +4
-3+++ b/qapi-schema.json@@ -2394,21 +2394,23 @@ ## # @vm-snapshot-save: # -# Create a snapshot of the whole virtual machine. If '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. +# Create a snapshot of the whole virtual machine. Provided 'tag' is used as +# human readable identifier. If there is already a snapshot with the same tag, +# force argument need to be "yes" to replace it.
s/need to be "yes"/needs to be 'true'/
qapi-schema.json line 2404
Quoted 6 lines
qapi-schema.json +1
-1# # The VM is automatically stopped and resumed and saving a snapshot can take # a long time. # -# @name: tag or id of new or existing snapshot +# @name: tag of new or existing snapshot
Given your new semantics, @name must be tag when @force is false; but the old HMP semantics allowed 'savevm 1' to rewrite snapshot id 1 regardless of the name, all while keeping the old tag. Does the new HMP code do an id lookup, and pass in the correct @name to the QMP code? Should the QMP code allow the same semantics of being able to pass @force=true and @name=id instead of the normal creation of @name=tag?
qapi-schema.json line 2406
Quoted 2 lines
qapi-schema.json +2
-0+# +# @force: specify whether existing snapshot is replaced or not
Based on the JSON below, this needs an #optional marking, as well as mentioning that the default is false.
qapi-schema.json line 2409
Quoted 3 lines
qapi-schema.json +0
-0# # Returns: Nothing on success # If an error occurs, GenericError with error message
Knowing that a creation failed due to a snapshot already existing by the same name or id might be worth a distinct error class (do we already have an error class that we could reuse?)
Signature · 2 lines
Eric Blake [email protected] +1-919-301-3266 Libvirt virtualization library http://libvirt.org
Re: [Qemu-devel] [PATCH 18/18] vm-snapshot-save: add force parameter
Quoted 31 lines · Eric Blake
Quoted 1 line · Pavel Hrdina
HMP command "savevm" now takes extra optional force parameter to specifi whether
s/specifi/specify/
Quoted 4 lines
replace existing snapshot or not.
QMP command "vm-snapshot-save" has also extra optional force parameter and name parameter isn't optional anymore.
When HMP omits the name, what name are you using in it's place? Either a nameless snapshot is okay (and QMP must expose it), or it is an error (and HMP must now be passing a reasonable name).
/me reads patch
Oh, there was always a name; the default name was a timestamp, and you moved the timestamp creation into HMP.
hmp-commands.hx ETEXI · line 268
Quoted 10 lines
+++ b/hmp-commands.hx
hmp-commands.hx +2
-3@@ -264,19 +264,19 @@ 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 = "name:s?,force:b?", + .params = "[tag|id] [on|off]",Rather than sticking 'force' as an optional parameter at the end, instead you want to add '-f' as a flag at the beginning.
Quoted 4 lines
.args_type = "force:-b,name:s?",
.params = "[-f] name"By doing this, you no longer need 17/18.
Thanks, I'll rewrite it for v2.
Quoted 29 lines
Quoted 4 lines
hmp-commands.hx +1
-0+ .help = "save a VM snapshot. To replace existing snapshot use force parameter.", .mhandler.cmd = hmp_vm_snapshot_save, },hmp-commands.hx ETEXI · line 278
Quoted 10 lines
hmp-commands.hx +3
-4STEXI @item savevm [@var{tag}|@var{id}] @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 -a snapshot with the same tag or ID, it is replaced. More info at -@ref{vm_snapshots}. +Create a snapshot of the whole virtual machine. Parameter "name" is optional. +If @var{tag} is provided, it is used as human readable identifier. If there is +already a snapshot with the same tag, force argument need to be "yes" tos/force argument need/the force argument needs/
qapi-schema.json line 2399
Quoted 11 lines
qapi-schema.json +4
-3+++ b/qapi-schema.json@@ -2394,21 +2394,23 @@ ## # @vm-snapshot-save: # -# Create a snapshot of the whole virtual machine. If '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. +# Create a snapshot of the whole virtual machine. Provided 'tag' is used as +# human readable identifier. If there is already a snapshot with the same tag, +# force argument need to be "yes" to replace it.s/need to be "yes"/needs to be 'true'/
Quoted 12 lines
qapi-schema.json line 2404
Quoted 6 lines
qapi-schema.json +1
-1# # The VM is automatically stopped and resumed and saving a snapshot can take # a long time. # -# @name: tag or id of new or existing snapshot +# @name: tag of new or existing snapshotGiven your new semantics, @name must be tag when @force is false; but the old HMP semantics allowed 'savevm 1' to rewrite snapshot id 1 regardless of the name, all while keeping the old tag. Does the new HMP code do an id lookup, and pass in the correct @name to the QMP code? Should the QMP code allow the same semantics of being able to pass @force=true and @name=id instead of the normal creation of @name=tag?
You can override existing snapshot specified by id. I'll fix the documentation.
Quoted 5 lines
qapi-schema.json line 2406
Quoted 2 lines
qapi-schema.json +2
-0+# +# @force: specify whether existing snapshot is replaced or notBased on the JSON below, this needs an #optional marking, as well as mentioning that the default is false.
Quoted 7 lines
qapi-schema.json line 2409
Quoted 3 lines
qapi-schema.json +0
-0# # Returns: Nothing on success # If an error occurs, GenericError with error messageKnowing that a creation failed due to a snapshot already existing by the same name or id might be worth a distinct error class (do we already have an error class that we could reuse?)
Regarding the Luiz's new error handling, for new errors we should use one error class.
Quoted 3 lines · On Wed, 15 Aug 2012 09:41:41 +0200 Pavel Hrdina <[email protected]> wrote:
This patch series convert these commands into qapi and intruduce QMP commands vm-snapshot-save, vm-snapshot-load, vm-snapshot-delete and query-vm-snapshots. It also rewrite error report for function used by these commands.
Unfortunately, most of the error conversions are wrong. I've commented on them, but the most important thing here is to decide how we should propagate the Error object in the block layer and what to do with its errno usage.
It's better to discuss this first before doing large changes. It might also be worth it to split this series and work on error propagation first.
I've CC'ed the block layer guys in one of my reviews to this series.