summaryrefslogtreecommitdiff
path: root/qemu-img.c
diff options
context:
space:
mode:
authorMax Reitz <mreitz@redhat.com>2014-10-24 15:57:38 +0200
committerStefan Hajnoczi <stefanha@redhat.com>2014-11-03 11:41:48 +0000
commit9a86fe489552d47b57c92782471ddfb9e7f702e2 (patch)
tree0edb41317a86504e14eb769a3a102342aadabee2 /qemu-img.c
parentd4a3238af567939f4c51bb074af1ce8839e2ce2d (diff)
qemu-img: Empty image after commit
After the top image has been committed, it should be emptied unless specified otherwise. Signed-off-by: Max Reitz <mreitz@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-id: 1414159063-25977-10-git-send-email-mreitz@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'qemu-img.c')
-rw-r--r--qemu-img.c34
1 files changed, 31 insertions, 3 deletions
diff --git a/qemu-img.c b/qemu-img.c
index 494146d6bb..cf8c01c13e 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -757,14 +757,14 @@ static int img_commit(int argc, char **argv)
const char *filename, *fmt, *cache;
BlockBackend *blk;
BlockDriverState *bs, *base_bs;
- bool quiet = false;
+ bool quiet = false, drop = false;
Error *local_err = NULL;
CommonBlockJobCBInfo cbi;
fmt = NULL;
cache = BDRV_DEFAULT_CACHE;
for(;;) {
- c = getopt(argc, argv, "f:ht:q");
+ c = getopt(argc, argv, "f:ht:dq");
if (c == -1) {
break;
}
@@ -779,6 +779,9 @@ static int img_commit(int argc, char **argv)
case 't':
cache = optarg;
break;
+ case 'd':
+ drop = true;
+ break;
case 'q':
quiet = true;
break;
@@ -789,7 +792,7 @@ static int img_commit(int argc, char **argv)
}
filename = argv[optind++];
- flags = BDRV_O_RDWR;
+ flags = BDRV_O_RDWR | BDRV_O_UNMAP;
ret = bdrv_parse_cache_flags(cache, &flags);
if (ret < 0) {
error_report("Invalid cache option: %s", cache);
@@ -822,7 +825,32 @@ static int img_commit(int argc, char **argv)
goto done;
}
+ /* The block job will swap base_bs and bs (which is not what we really want
+ * here, but okay) and unref base_bs (after the swap, i.e., the old top
+ * image). In order to still be able to empty that top image afterwards,
+ * increment the reference counter here preemptively. */
+ if (!drop) {
+ bdrv_ref(base_bs);
+ }
+
run_block_job(bs->job, &local_err);
+ if (local_err) {
+ goto unref_backing;
+ }
+
+ if (!drop && base_bs->drv->bdrv_make_empty) {
+ ret = base_bs->drv->bdrv_make_empty(base_bs);
+ if (ret) {
+ error_setg_errno(&local_err, -ret, "Could not empty %s",
+ filename);
+ goto unref_backing;
+ }
+ }
+
+unref_backing:
+ if (!drop) {
+ bdrv_unref(base_bs);
+ }
done:
blk_unref(blk);