mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 11:39:53 +00:00
qemu-img: Implement commit like QMP
qemu-img should use QMP commands whenever possible in order to ensure feature completeness of both online and offline image operations. As qemu-img itself has no access to QMP (since this would basically require just everything being linked into qemu-img), imitate QMP's implementation of block-commit by using commit_active_start() and then waiting for the block job to finish. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 1414159063-25977-9-git-send-email-mreitz@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
b21c76529d
commit
d4a3238af5
@ -9,7 +9,7 @@ block-obj-y += block-backend.o snapshot.o qapi.o
|
||||
block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o
|
||||
block-obj-$(CONFIG_POSIX) += raw-posix.o
|
||||
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
|
||||
block-obj-y += null.o
|
||||
block-obj-y += null.o mirror.o
|
||||
|
||||
block-obj-y += nbd.o nbd-client.o sheepdog.o
|
||||
block-obj-$(CONFIG_LIBISCSI) += iscsi.o
|
||||
@ -23,7 +23,6 @@ block-obj-y += accounting.o
|
||||
|
||||
common-obj-y += stream.o
|
||||
common-obj-y += commit.o
|
||||
common-obj-y += mirror.o
|
||||
common-obj-y += backup.o
|
||||
|
||||
iscsi.o-cflags := $(LIBISCSI_CFLAGS)
|
||||
|
78
qemu-img.c
78
qemu-img.c
@ -31,6 +31,7 @@
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/blockjob.h"
|
||||
#include "block/qapi.h"
|
||||
#include <getopt.h>
|
||||
|
||||
@ -722,13 +723,43 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct CommonBlockJobCBInfo {
|
||||
BlockDriverState *bs;
|
||||
Error **errp;
|
||||
} CommonBlockJobCBInfo;
|
||||
|
||||
static void common_block_job_cb(void *opaque, int ret)
|
||||
{
|
||||
CommonBlockJobCBInfo *cbi = opaque;
|
||||
|
||||
if (ret < 0) {
|
||||
error_setg_errno(cbi->errp, -ret, "Block job failed");
|
||||
}
|
||||
|
||||
/* Drop this block job's reference */
|
||||
bdrv_unref(cbi->bs);
|
||||
}
|
||||
|
||||
static void run_block_job(BlockJob *job, Error **errp)
|
||||
{
|
||||
AioContext *aio_context = bdrv_get_aio_context(job->bs);
|
||||
|
||||
do {
|
||||
aio_poll(aio_context, true);
|
||||
} while (!job->ready);
|
||||
|
||||
block_job_complete_sync(job, errp);
|
||||
}
|
||||
|
||||
static int img_commit(int argc, char **argv)
|
||||
{
|
||||
int c, ret, flags;
|
||||
const char *filename, *fmt, *cache;
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
BlockDriverState *bs, *base_bs;
|
||||
bool quiet = false;
|
||||
Error *local_err = NULL;
|
||||
CommonBlockJobCBInfo cbi;
|
||||
|
||||
fmt = NULL;
|
||||
cache = BDRV_DEFAULT_CACHE;
|
||||
@ -771,29 +802,38 @@ static int img_commit(int argc, char **argv)
|
||||
}
|
||||
bs = blk_bs(blk);
|
||||
|
||||
ret = bdrv_commit(bs);
|
||||
switch(ret) {
|
||||
case 0:
|
||||
qprintf(quiet, "Image committed.\n");
|
||||
break;
|
||||
case -ENOENT:
|
||||
error_report("No disk inserted");
|
||||
break;
|
||||
case -EACCES:
|
||||
error_report("Image is read-only");
|
||||
break;
|
||||
case -ENOTSUP:
|
||||
error_report("Image is already committed");
|
||||
break;
|
||||
default:
|
||||
error_report("Error while committing image");
|
||||
break;
|
||||
/* This is different from QMP, which by default uses the deepest file in the
|
||||
* backing chain (i.e., the very base); however, the traditional behavior of
|
||||
* qemu-img commit is using the immediate backing file. */
|
||||
base_bs = bs->backing_hd;
|
||||
if (!base_bs) {
|
||||
error_setg(&local_err, "Image does not have a backing file");
|
||||
goto done;
|
||||
}
|
||||
|
||||
cbi = (CommonBlockJobCBInfo){
|
||||
.errp = &local_err,
|
||||
.bs = bs,
|
||||
};
|
||||
|
||||
commit_active_start(bs, base_bs, 0, BLOCKDEV_ON_ERROR_REPORT,
|
||||
common_block_job_cb, &cbi, &local_err);
|
||||
if (local_err) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
run_block_job(bs->job, &local_err);
|
||||
|
||||
done:
|
||||
blk_unref(blk);
|
||||
if (ret) {
|
||||
|
||||
if (local_err) {
|
||||
qerror_report_err(local_err);
|
||||
error_free(local_err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
qprintf(quiet, "Image committed.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user