Browse Source

qemu-img: Specify backing file for commit

Introduce a new parameter for qemu-img commit which may be used to
explicitly specify the backing file into which an image should be
committed if the backing chain has more than a single layer.

[Applied Eric Blake's qemu-img.texi documentation rewording
--Stefan]

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-12-git-send-email-mreitz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Max Reitz 10 năm trước cách đây
mục cha
commit
1b22bffd82
3 tập tin đã thay đổi với 36 bổ sung12 xóa
  1. 2 2
      qemu-img-cmds.hx
  2. 23 9
      qemu-img.c
  3. 11 1
      qemu-img.texi

+ 2 - 2
qemu-img-cmds.hx

@@ -22,9 +22,9 @@ STEXI
 ETEXI
 ETEXI
 
 
 DEF("commit", img_commit,
 DEF("commit", img_commit,
-    "commit [-q] [-f fmt] [-t cache] [-d] [-p] filename")
+    "commit [-q] [-f fmt] [-t cache] [-b base] [-d] [-p] filename")
 STEXI
 STEXI
-@item commit [-q] [-f @var{fmt}] [-t @var{cache}] [-d] [-p] @var{filename}
+@item commit [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename}
 ETEXI
 ETEXI
 
 
 DEF("compare", img_compare,
 DEF("compare", img_compare,

+ 23 - 9
qemu-img.c

@@ -759,7 +759,7 @@ static void run_block_job(BlockJob *job, Error **errp)
 static int img_commit(int argc, char **argv)
 static int img_commit(int argc, char **argv)
 {
 {
     int c, ret, flags;
     int c, ret, flags;
-    const char *filename, *fmt, *cache;
+    const char *filename, *fmt, *cache, *base;
     BlockBackend *blk;
     BlockBackend *blk;
     BlockDriverState *bs, *base_bs;
     BlockDriverState *bs, *base_bs;
     bool progress = false, quiet = false, drop = false;
     bool progress = false, quiet = false, drop = false;
@@ -768,8 +768,9 @@ static int img_commit(int argc, char **argv)
 
 
     fmt = NULL;
     fmt = NULL;
     cache = BDRV_DEFAULT_CACHE;
     cache = BDRV_DEFAULT_CACHE;
+    base = NULL;
     for(;;) {
     for(;;) {
-        c = getopt(argc, argv, "f:ht:dpq");
+        c = getopt(argc, argv, "f:ht:b:dpq");
         if (c == -1) {
         if (c == -1) {
             break;
             break;
         }
         }
@@ -784,6 +785,11 @@ static int img_commit(int argc, char **argv)
         case 't':
         case 't':
             cache = optarg;
             cache = optarg;
             break;
             break;
+        case 'b':
+            base = optarg;
+            /* -b implies -d */
+            drop = true;
+            break;
         case 'd':
         case 'd':
             drop = true;
             drop = true;
             break;
             break;
@@ -822,13 +828,21 @@ static int img_commit(int argc, char **argv)
     qemu_progress_init(progress, 1.f);
     qemu_progress_init(progress, 1.f);
     qemu_progress_print(0.f, 100);
     qemu_progress_print(0.f, 100);
 
 
-    /* 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;
+    if (base) {
+        base_bs = bdrv_find_backing_image(bs, base);
+        if (!base_bs) {
+            error_set(&local_err, QERR_BASE_NOT_FOUND, base);
+            goto done;
+        }
+    } else {
+        /* 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){
     cbi = (CommonBlockJobCBInfo){

+ 11 - 1
qemu-img.texi

@@ -167,7 +167,7 @@ this case. @var{backing_file} will never be modified unless you use the
 The size can also be specified using the @var{size} option with @code{-o},
 The size can also be specified using the @var{size} option with @code{-o},
 it doesn't need to be specified separately in this case.
 it doesn't need to be specified separately in this case.
 
 
-@item commit [-q] [-f @var{fmt}] [-t @var{cache}] [-d] [-p] @var{filename}
+@item commit [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename}
 
 
 Commit the changes recorded in @var{filename} in its base image or backing file.
 Commit the changes recorded in @var{filename} in its base image or backing file.
 If the backing file is smaller than the snapshot, then the backing file will be
 If the backing file is smaller than the snapshot, then the backing file will be
@@ -180,6 +180,16 @@ The image @var{filename} is emptied after the operation has succeeded. If you do
 not need @var{filename} afterwards and intend to drop it, you may skip emptying
 not need @var{filename} afterwards and intend to drop it, you may skip emptying
 @var{filename} by specifying the @code{-d} flag.
 @var{filename} by specifying the @code{-d} flag.
 
 
+If the backing chain of the given image file @var{filename} has more than one
+layer, the backing file into which the changes will be committed may be
+specified as @var{base} (which has to be part of @var{filename}'s backing
+chain). If @var{base} is not specified, the immediate backing file of the top
+image (which is @var{filename}) will be used. For reasons of consistency,
+explicitly specifying @var{base} will always imply @code{-d} (since emptying an
+image after committing to an indirect backing file would lead to different data
+being read from the image due to content in the intermediate backing chain
+overruling the commit target).
+
 @item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-s] [-q] @var{filename1} @var{filename2}
 @item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-s] [-q] @var{filename1} @var{filename2}
 
 
 Check if two images have the same content. You can compare images with
 Check if two images have the same content. You can compare images with