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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user