Re: [Qemu-devel] [PATCH 2/2] Add the blockdev-reopen and blockdev-migrate commands
Kevin Wolf kw...@redhat.com writes: Am 24.02.2012 12:37, schrieb Federico Simoncelli: [...] diff --git a/blockdev.c b/blockdev.c index 2c132a3..1df2542 100644 --- a/blockdev.c +++ b/blockdev.c [...] +void qmp_blockdev_migrate(const char *device, BlockMigrateOp mode, + const char *destination, bool has_new_image_file, + const char *new_image_file, Error **errp) +{ +BlockDriverState *bs; +BlockDriver *drv; +int i, j, escape; +char filename[2048]; + +bs = bdrv_find(device); +if (!bs) { +error_set(errp, QERR_DEVICE_NOT_FOUND, device); +return; +} +if (bdrv_in_use(bs)) { +error_set(errp, QERR_DEVICE_IN_USE, device); +return; +} + +if (mode == BLOCK_MIGRATE_OP_MIRROR) { Move into a separate function? +drv = bdrv_find_format(blkmirror); +if (!drv) { +error_set(errp, QERR_INVALID_BLOCK_FORMAT, blkmirror); +return; +} + +if (!has_new_image_file) { +new_image_file = bs-filename; +} + +pstrcpy(filename, sizeof(filename), blkmirror:); +i = strlen(blkmirror:); + +escape = 0; +for (j = 0; j strlen(new_image_file); j++) { + loop: +if (!(i sizeof(filename) - 2)) { +error_set(errp, QERR_INVALID_PARAMETER_VALUE, + new-image-file, shorter filename); +return; +} + +if (new_image_file[j] == ':' || new_image_file[j] == '\\') { Markus suggested that using comma for the separator is better even though it requires escaping. It would allow to parse the option string with QemuOpts. Yes, I did. While I'm no particular friend of QemuOpts, inventing more ad hoc syntaxes is even worse. On the other hand, many block drivers already do, often a colon syntax similar to yours. But not all. I guess consistency is a lost cause there, as is generality (support for arbitrary filenames). Maybe it's best to concede defeat, do another ad hoc syntax now, and hope we can replace the whole -drive mess by something saner eventually. +if (!escape) { +filename[i++] = '\\', escape = 1; +goto loop; +} else { +escape = 0; +} +} + +filename[i++] = new_image_file[j]; +} Looks like a string helper for qemu-option.c (it contains the parser, so keeping the escaping nearby would make sense). + +if (i + strlen(destination) + 2 sizeof(filename)) { +error_set(errp, QERR_INVALID_PARAMETER_VALUE, + destination, shorter filename); +return; +} + +filename[i++] = ':'; +pstrcpy(filename + i, sizeof(filename) - i - 2, destination); + +change_blockdev_image(device, filename, blkmirror, false, errp); +} else if (mode == BLOCK_MIGRATE_OP_STREAM) { +error_set(errp, QERR_NOT_SUPPORTED); Why even define it then? +} +} + static void eject_device(BlockDriverState *bs, int force, Error **errp) { if (bdrv_in_use(bs)) { diff --git a/hmp-commands.hx b/hmp-commands.hx index 573b823..ccb1f62 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -886,6 +886,42 @@ Snapshot device, using snapshot file as target if provided ETEXI { +.name = blkdev_reopen, NACK on the name. Let's reserve blkdev_*/blockdev_* for the proper API Yes, please. (that we'll release with the qemu version that comes with Hurd 1.0). /me hides. drive_* would align well with the existing drive_add/del commands. Agree. [...] diff --git a/qapi-schema.json b/qapi-schema.json index d02ee86..c86796a 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1136,6 +1136,69 @@ 'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str' } } ## +# @blockdev-reopen +# +# Assigns a new image file to a device. +# +# @device: the name of the device for which we are chainging the image file. +# +# @new-image-file: the target of the new image. If the file doesn't exists the +# command will fail. +# +# @format: #optional the format of the new image, default is 'qcow2'. +# +# Returns: nothing on success +# If @device is not a valid block device, DeviceNotFound +# If @new-image-file can't be opened, OpenFileFailed +# If @format is invalid, InvalidBlockFormat +# +# Since 1.1 +## + +{ 'command': 'blockdev-reopen', + 'data': { 'device': 'str', 'new-image-file': 'str', '*format': 'str' } } Same consideration on the name. Also I think we should immediately mark the command as deprecated (I think there is precedence for it, though I can't remember which command it was). This is not an interface we'll want to keep long term. Deprecated isn't
Re: [Qemu-devel] [PATCH 2/2] Add the blockdev-reopen and blockdev-migrate commands
Am 24.02.2012 12:37, schrieb Federico Simoncelli: Signed-off-by: Federico Simoncelli fsimo...@redhat.com --- block/blkmirror.c |2 +- blockdev.c| 109 +++-- hmp-commands.hx | 36 + hmp.c | 30 ++ hmp.h |2 + qapi-schema.json | 63 ++ 6 files changed, 229 insertions(+), 13 deletions(-) diff --git a/block/blkmirror.c b/block/blkmirror.c index 39927c8..49e3381 100644 --- a/block/blkmirror.c +++ b/block/blkmirror.c @@ -81,7 +81,7 @@ static int blkmirror_open(BlockDriverState *bs, const char *filename, int flags) bdrv_delete(m-bs[0]); return -ENOMEM; } -ret = bdrv_open(m-bs[1], filename, flags, NULL); +ret = bdrv_open(m-bs[1], filename, flags | BDRV_O_NO_BACKING, NULL); if (ret 0) { bdrv_delete(m-bs[0]); return ret; Was this hunk meant to be in patch 1? diff --git a/blockdev.c b/blockdev.c index 2c132a3..1df2542 100644 --- a/blockdev.c +++ b/blockdev.c @@ -646,9 +646,8 @@ void do_commit(Monitor *mon, const QDict *qdict) } } -void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, -bool has_format, const char *format, -Error **errp) +static void change_blockdev_image(const char *device, const char *new_image_file, + const char *format, bool create, Error **errp) { BlockDriverState *bs; BlockDriver *drv, *old_drv, *proto_drv; @@ -671,7 +670,7 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, old_drv = bs-drv; flags = bs-open_flags; -if (!has_format) { +if (!format) { format = qcow2; } @@ -681,24 +680,26 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, return; } -proto_drv = bdrv_find_protocol(snapshot_file); +proto_drv = bdrv_find_protocol(new_image_file); if (!proto_drv) { error_set(errp, QERR_INVALID_BLOCK_FORMAT, format); return; } -ret = bdrv_img_create(snapshot_file, format, bs-filename, - bs-drv-format_name, NULL, -1, flags); -if (ret) { -error_set(errp, QERR_UNDEFINED_ERROR); -return; +if (create) { +ret = bdrv_img_create(new_image_file, format, bs-filename, + bs-drv-format_name, NULL, -1, flags); +if (ret) { +error_set(errp, QERR_UNDEFINED_ERROR); +return; +} } bdrv_drain_all(); bdrv_flush(bs); bdrv_close(bs); -ret = bdrv_open(bs, snapshot_file, flags, drv); +ret = bdrv_open(bs, new_image_file, flags, drv); /* * If reopening the image file we just created fails, fall back * and try to re-open the original image. If that fails too, we @@ -709,11 +710,95 @@ void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, if (ret != 0) { error_set(errp, QERR_OPEN_FILE_FAILED, old_filename); } else { -error_set(errp, QERR_OPEN_FILE_FAILED, snapshot_file); +error_set(errp, QERR_OPEN_FILE_FAILED, new_image_file); } } } +void qmp_blockdev_reopen(const char *device, const char *new_image_file, + bool has_format, const char *format, Error **errp) +{ +change_blockdev_image(device, new_image_file, + has_format ? format : NULL, false, errp); +} + +void qmp_blockdev_snapshot_sync(const char *device, const char *snapshot_file, +bool has_format, const char *format, +Error **errp) +{ +change_blockdev_image(device, snapshot_file, + has_format ? format : NULL, true, errp); +} + +void qmp_blockdev_migrate(const char *device, BlockMigrateOp mode, + const char *destination, bool has_new_image_file, + const char *new_image_file, Error **errp) +{ +BlockDriverState *bs; +BlockDriver *drv; +int i, j, escape; +char filename[2048]; + +bs = bdrv_find(device); +if (!bs) { +error_set(errp, QERR_DEVICE_NOT_FOUND, device); +return; +} +if (bdrv_in_use(bs)) { +error_set(errp, QERR_DEVICE_IN_USE, device); +return; +} + +if (mode == BLOCK_MIGRATE_OP_MIRROR) { Move into a separate function? +drv = bdrv_find_format(blkmirror); +if (!drv) { +error_set(errp, QERR_INVALID_BLOCK_FORMAT, blkmirror); +return; +} + +if (!has_new_image_file) { +new_image_file = bs-filename; +} + +
Re: [Qemu-devel] [PATCH 2/2] Add the blockdev-reopen and blockdev-migrate commands
- Original Message - From: Kevin Wolf kw...@redhat.com To: Federico Simoncelli fsimo...@redhat.com Cc: qemu-devel@nongnu.org, Marcelo Tosatti mtosa...@redhat.com, lcapitul...@redhat.com, Paolo Bonzini pbonz...@redhat.com, Markus Armbruster arm...@redhat.com Sent: Friday, February 24, 2012 1:03:08 PM Subject: Re: [PATCH 2/2] Add the blockdev-reopen and blockdev-migrate commands Am 24.02.2012 12:37, schrieb Federico Simoncelli: Signed-off-by: Federico Simoncelli fsimo...@redhat.com --- block/blkmirror.c |2 +- blockdev.c| 109 +++-- hmp-commands.hx | 36 + hmp.c | 30 ++ hmp.h |2 + qapi-schema.json | 63 ++ 6 files changed, 229 insertions(+), 13 deletions(-) diff --git a/block/blkmirror.c b/block/blkmirror.c index 39927c8..49e3381 100644 --- a/block/blkmirror.c +++ b/block/blkmirror.c @@ -81,7 +81,7 @@ static int blkmirror_open(BlockDriverState *bs, const char *filename, int flags) bdrv_delete(m-bs[0]); return -ENOMEM; } -ret = bdrv_open(m-bs[1], filename, flags, NULL); +ret = bdrv_open(m-bs[1], filename, flags | BDRV_O_NO_BACKING, NULL); if (ret 0) { bdrv_delete(m-bs[0]); return ret; Was this hunk meant to be in patch 1? Not necessarily, I thought a lot about it. I didn't want to modify Marcelo's patch too much. This flag is actually mandatory only to make blockdev-migrate work with a destination that doesn't have a backing file yet, so I thought it was more appropriate to squash it here. -- Federico
Re: [Qemu-devel] [PATCH 2/2] Add the blockdev-reopen and blockdev-migrate commands
On 02/24/2012 01:03 PM, Kevin Wolf wrote: + loop: +if (!(i sizeof(filename) - 2)) { +error_set(errp, QERR_INVALID_PARAMETER_VALUE, + new-image-file, shorter filename); +return; +} + +if (new_image_file[j] == ':' || new_image_file[j] == '\\') { Markus suggested that using comma for the separator is better even though it requires escaping. It would allow to parse the option string with QemuOpts. Isn't that a bit overengineering for an internal interface? +if (!escape) { +filename[i++] = '\\', escape = 1; +goto loop; +} else { +escape = 0; +} +} + +filename[i++] = new_image_file[j]; +} Looks like a string helper for qemu-option.c (it contains the parser, so keeping the escaping nearby would make sense). + +if (i + strlen(destination) + 2 sizeof(filename)) { +error_set(errp, QERR_INVALID_PARAMETER_VALUE, + destination, shorter filename); +return; +} + +filename[i++] = ':'; +pstrcpy(filename + i, sizeof(filename) - i - 2, destination); + +change_blockdev_image(device, filename, blkmirror, false, errp); +} else if (mode == BLOCK_MIGRATE_OP_STREAM) { +error_set(errp, QERR_NOT_SUPPORTED); Why even define it then? Because it's the default for the HMP. Until we have live merging, mirror mode cannot be consider anything more than a hack. ## +# @blockdev-reopen +# +# Assigns a new image file to a device. +# +# @device: the name of the device for which we are chainging the image file. +# +# @new-image-file: the target of the new image. If the file doesn't exists the +# command will fail. +# +# @format: #optional the format of the new image, default is 'qcow2'. +# +# Returns: nothing on success +# If @device is not a valid block device, DeviceNotFound +# If @new-image-file can't be opened, OpenFileFailed +# If @format is invalid, InvalidBlockFormat +# +# Since 1.1 +## + +{ 'command': 'blockdev-reopen', + 'data': { 'device': 'str', 'new-image-file': 'str', '*format': 'str' } } Same consideration on the name. Also I think we should immediately mark the command as deprecated (I think there is precedence for it, though I can't remember which command it was). This is not an interface we'll want to keep long term. What about blockdev-snapshot-sync/snapshot_blkdev? Paolo
Re: [Qemu-devel] [PATCH 2/2] Add the blockdev-reopen and blockdev-migrate commands
On Fri, 24 Feb 2012 13:03:08 +0100 Kevin Wolf kw...@redhat.com wrote: static void eject_device(BlockDriverState *bs, int force, Error **errp) { if (bdrv_in_use(bs)) { diff --git a/hmp-commands.hx b/hmp-commands.hx index 573b823..ccb1f62 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -886,6 +886,42 @@ Snapshot device, using snapshot file as target if provided ETEXI { +.name = blkdev_reopen, NACK on the name. Let's reserve blkdev_*/blockdev_* for the proper API (that we'll release with the qemu version that comes with Hurd 1.0). lol. ## +# @blockdev-reopen +# +# Assigns a new image file to a device. +# +# @device: the name of the device for which we are chainging the image file. +# +# @new-image-file: the target of the new image. If the file doesn't exists the +# command will fail. +# +# @format: #optional the format of the new image, default is 'qcow2'. +# +# Returns: nothing on success +# If @device is not a valid block device, DeviceNotFound +# If @new-image-file can't be opened, OpenFileFailed +# If @format is invalid, InvalidBlockFormat +# +# Since 1.1 +## + +{ 'command': 'blockdev-reopen', + 'data': { 'device': 'str', 'new-image-file': 'str', '*format': 'str' } } Same consideration on the name. Also I think we should immediately mark the command as deprecated (I think there is precedence for it, though I can't remember which command it was). This is not an interface we'll want to keep long term. We can only mark an interface as deprecated when there's a substitute for it.