9ae3a8
From a4e7f2adeadd8c03acd509028c07c7114379af10 Mon Sep 17 00:00:00 2001
9ae3a8
From: Max Reitz <mreitz@redhat.com>
9ae3a8
Date: Fri, 24 Oct 2014 08:17:57 +0200
9ae3a8
Subject: [PATCH 09/19] qemu-img: Allow source cache mode specification
9ae3a8
9ae3a8
Message-id: <1414138680-19600-2-git-send-email-mreitz@redhat.com>
9ae3a8
Patchwork-id: 61862
9ae3a8
O-Subject: [RHEL-7.1 qemu-kvm PATCH v2 1/4] qemu-img: Allow source cache mode specification
9ae3a8
Bugzilla: 1138691
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
9ae3a8
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
9ae3a8
Many qemu-img subcommands only read the source file(s) once. For these
9ae3a8
use cases, a full write-back cache is unnecessary and mainly clutters
9ae3a8
host cache memory. Though this is generally no concern as cache memory
9ae3a8
is freely available and can be scaled by the host OS, it may become a
9ae3a8
concern with thin provisioning.
9ae3a8
9ae3a8
For these cases, it makes sense to allow users to freely specify the
9ae3a8
source cache mode (e.g. use no cache at all).
9ae3a8
9ae3a8
This commit adds a new switch (-T) for the qemu-img subcommands check,
9ae3a8
compare, convert and rebase to specify the cache to be used for source
9ae3a8
images (the backing file in case of rebase).
9ae3a8
9ae3a8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9ae3a8
Reviewed-by: Eric Blake <eblake@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit 40055951a7afbfc037c6c7351d72a5c5d83ed99b)
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
9ae3a8
Conflicts:
9ae3a8
	qemu-img-cmds.hx
9ae3a8
	qemu-img.c
9ae3a8
	qemu-img.texi
9ae3a8
9ae3a8
Conflicts due to bdrv_open() working differently downstream
9ae3a8
(pre-O_PROTOCOL and no reference parameter), and there are more options
9ae3a8
to qemu-img convert upstream.
9ae3a8
9ae3a8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9ae3a8
---
9ae3a8
 qemu-img-cmds.hx | 16 ++++++------
9ae3a8
 qemu-img.c       | 76 +++++++++++++++++++++++++++++++++++++++++++++-----------
9ae3a8
 qemu-img.texi    | 14 ++++++++---
9ae3a8
 3 files changed, 79 insertions(+), 27 deletions(-)
9ae3a8
9ae3a8
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
9ae3a8
index da1d965..e590d46 100644
9ae3a8
--- a/qemu-img-cmds.hx
9ae3a8
+++ b/qemu-img-cmds.hx
9ae3a8
@@ -10,9 +10,9 @@ STEXI
9ae3a8
 ETEXI
9ae3a8
 
9ae3a8
 DEF("check", img_check,
9ae3a8
-    "check [-q] [-f fmt] [--output=ofmt]  [-r [leaks | all]] filename")
9ae3a8
+    "check [-q] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename")
9ae3a8
 STEXI
9ae3a8
-@item check [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] @var{filename}
9ae3a8
+@item check [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
9ae3a8
 ETEXI
9ae3a8
 
9ae3a8
 DEF("create", img_create,
9ae3a8
@@ -28,15 +28,15 @@ STEXI
9ae3a8
 ETEXI
9ae3a8
 
9ae3a8
 DEF("compare", img_compare,
9ae3a8
-    "compare [-f fmt] [-F fmt] [-p] [-q] [-s] filename1 filename2")
9ae3a8
+    "compare [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2")
9ae3a8
 STEXI
9ae3a8
-@item compare [-f @var{fmt}] [-F @var{fmt}] [-p] [-q] [-s] @var{filename1} @var{filename2}
9ae3a8
+@item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2}
9ae3a8
 ETEXI
9ae3a8
 
9ae3a8
 DEF("convert", img_convert,
9ae3a8
-    "convert [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename")
9ae3a8
+    "convert [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_name] [-S sparse_size] filename [filename2 [...]] output_filename")
9ae3a8
 STEXI
9ae3a8
-@item convert [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
9ae3a8
+@item convert [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
9ae3a8
 ETEXI
9ae3a8
 
9ae3a8
 DEF("info", img_info,
9ae3a8
@@ -58,9 +58,9 @@ STEXI
9ae3a8
 ETEXI
9ae3a8
 
9ae3a8
 DEF("rebase", img_rebase,
9ae3a8
-    "rebase [-q] [-f fmt] [-t cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
9ae3a8
+    "rebase [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
9ae3a8
 STEXI
9ae3a8
-@item rebase [-q] [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
9ae3a8
+@item rebase [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
9ae3a8
 ETEXI
9ae3a8
 
9ae3a8
 DEF("resize", img_resize,
9ae3a8
diff --git a/qemu-img.c b/qemu-img.c
9ae3a8
index fe0ac65..25fdc37 100644
9ae3a8
--- a/qemu-img.c
9ae3a8
+++ b/qemu-img.c
9ae3a8
@@ -84,6 +84,7 @@ static void help(void)
9ae3a8
            "  'cache' is the cache mode used to write the output disk image, the valid\n"
9ae3a8
            "    options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
9ae3a8
            "    'directsync' and 'unsafe' (default for convert)\n"
9ae3a8
+           "  'src_cache' in contrast is the cache mode used to read input disk images\n"
9ae3a8
            "  'size' is the disk image size in bytes. Optional suffixes\n"
9ae3a8
            "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
9ae3a8
            "    and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
9ae3a8
@@ -553,7 +554,7 @@ static int img_check(int argc, char **argv)
9ae3a8
 {
9ae3a8
     int c, ret;
9ae3a8
     OutputFormat output_format = OFORMAT_HUMAN;
9ae3a8
-    const char *filename, *fmt, *output;
9ae3a8
+    const char *filename, *fmt, *output, *cache;
9ae3a8
     BlockDriverState *bs;
9ae3a8
     int fix = 0;
9ae3a8
     int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
9ae3a8
@@ -562,6 +563,7 @@ static int img_check(int argc, char **argv)
9ae3a8
 
9ae3a8
     fmt = NULL;
9ae3a8
     output = NULL;
9ae3a8
+    cache = BDRV_DEFAULT_CACHE;
9ae3a8
     for(;;) {
9ae3a8
         int option_index = 0;
9ae3a8
         static const struct option long_options[] = {
9ae3a8
@@ -571,7 +573,7 @@ static int img_check(int argc, char **argv)
9ae3a8
             {"output", required_argument, 0, OPTION_OUTPUT},
9ae3a8
             {0, 0, 0, 0}
9ae3a8
         };
9ae3a8
-        c = getopt_long(argc, argv, "f:hr:q",
9ae3a8
+        c = getopt_long(argc, argv, "hf:r:T:q",
9ae3a8
                         long_options, &option_index);
9ae3a8
         if (c == -1) {
9ae3a8
             break;
9ae3a8
@@ -598,6 +600,9 @@ static int img_check(int argc, char **argv)
9ae3a8
         case OPTION_OUTPUT:
9ae3a8
             output = optarg;
9ae3a8
             break;
9ae3a8
+        case 'T':
9ae3a8
+            cache = optarg;
9ae3a8
+            break;
9ae3a8
         case 'q':
9ae3a8
             quiet = true;
9ae3a8
             break;
9ae3a8
@@ -617,6 +622,12 @@ static int img_check(int argc, char **argv)
9ae3a8
         return 1;
9ae3a8
     }
9ae3a8
 
9ae3a8
+    ret = bdrv_parse_cache_flags(cache, &flags);
9ae3a8
+    if (ret < 0) {
9ae3a8
+        error_report("Invalid source cache option: %s", cache);
9ae3a8
+        return 1;
9ae3a8
+    }
9ae3a8
+
9ae3a8
     bs = bdrv_new_open("image", filename, fmt, flags, true, quiet);
9ae3a8
     if (!bs) {
9ae3a8
         return 1;
9ae3a8
@@ -911,7 +922,7 @@ static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
9ae3a8
  */
9ae3a8
 static int img_compare(int argc, char **argv)
9ae3a8
 {
9ae3a8
-    const char *fmt1 = NULL, *fmt2 = NULL, *filename1, *filename2;
9ae3a8
+    const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
9ae3a8
     BlockDriverState *bs1, *bs2;
9ae3a8
     int64_t total_sectors1, total_sectors2;
9ae3a8
     uint8_t *buf1 = NULL, *buf2 = NULL;
9ae3a8
@@ -919,6 +930,7 @@ static int img_compare(int argc, char **argv)
9ae3a8
     int allocated1, allocated2;
9ae3a8
     int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */
9ae3a8
     bool progress = false, quiet = false, strict = false;
9ae3a8
+    int flags;
9ae3a8
     int64_t total_sectors;
9ae3a8
     int64_t sector_num = 0;
9ae3a8
     int64_t nb_sectors;
9ae3a8
@@ -926,8 +938,9 @@ static int img_compare(int argc, char **argv)
9ae3a8
     uint64_t bs_sectors;
9ae3a8
     uint64_t progress_base;
9ae3a8
 
9ae3a8
+    cache = BDRV_DEFAULT_CACHE;
9ae3a8
     for (;;) {
9ae3a8
-        c = getopt(argc, argv, "hpf:F:sq");
9ae3a8
+        c = getopt(argc, argv, "hf:F:T:pqs");
9ae3a8
         if (c == -1) {
9ae3a8
             break;
9ae3a8
         }
9ae3a8
@@ -942,6 +955,9 @@ static int img_compare(int argc, char **argv)
9ae3a8
         case 'F':
9ae3a8
             fmt2 = optarg;
9ae3a8
             break;
9ae3a8
+        case 'T':
9ae3a8
+            cache = optarg;
9ae3a8
+            break;
9ae3a8
         case 'p':
9ae3a8
             progress = true;
9ae3a8
             break;
9ae3a8
@@ -966,17 +982,25 @@ static int img_compare(int argc, char **argv)
9ae3a8
     filename1 = argv[optind++];
9ae3a8
     filename2 = argv[optind++];
9ae3a8
 
9ae3a8
+    flags = BDRV_O_FLAGS;
9ae3a8
+    ret = bdrv_parse_cache_flags(cache, &flags);
9ae3a8
+    if (ret < 0) {
9ae3a8
+        error_report("Invalid source cache option: %s", cache);
9ae3a8
+        ret = 2;
9ae3a8
+        goto out3;
9ae3a8
+    }
9ae3a8
+
9ae3a8
     /* Initialize before goto out */
9ae3a8
     qemu_progress_init(progress, 2.0);
9ae3a8
 
9ae3a8
-    bs1 = bdrv_new_open("image 1", filename1, fmt1, BDRV_O_FLAGS, true, quiet);
9ae3a8
+    bs1 = bdrv_new_open("image 1", filename1, fmt1, flags, true, quiet);
9ae3a8
     if (!bs1) {
9ae3a8
         error_report("Can't open file %s", filename1);
9ae3a8
         ret = 2;
9ae3a8
         goto out3;
9ae3a8
     }
9ae3a8
 
9ae3a8
-    bs2 = bdrv_new_open("image 2", filename2, fmt2, BDRV_O_FLAGS, true, quiet);
9ae3a8
+    bs2 = bdrv_new_open("image 2", filename2, fmt2, flags, true, quiet);
9ae3a8
     if (!bs2) {
9ae3a8
         error_report("Can't open file %s", filename2);
9ae3a8
         ret = 2;
9ae3a8
@@ -1145,8 +1169,8 @@ static int img_convert(int argc, char **argv)
9ae3a8
 {
9ae3a8
     int c, n, n1, bs_n, bs_i, compress, cluster_sectors, skip_create;
9ae3a8
     int64_t ret = 0;
9ae3a8
-    int progress = 0, flags;
9ae3a8
-    const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
9ae3a8
+    int progress = 0, flags, src_flags;
9ae3a8
+    const char *fmt, *out_fmt, *cache, *src_cache, *out_baseimg, *out_filename;
9ae3a8
     BlockDriver *drv, *proto_drv;
9ae3a8
     BlockDriverState **bs = NULL, *out_bs = NULL;
9ae3a8
     int64_t total_sectors, nb_sectors, sector_num, bs_offset,
9ae3a8
@@ -1167,11 +1191,12 @@ static int img_convert(int argc, char **argv)
9ae3a8
     fmt = NULL;
9ae3a8
     out_fmt = "raw";
9ae3a8
     cache = "unsafe";
9ae3a8
+    src_cache = BDRV_DEFAULT_CACHE;
9ae3a8
     out_baseimg = NULL;
9ae3a8
     compress = 0;
9ae3a8
     skip_create = 0;
9ae3a8
     for(;;) {
9ae3a8
-        c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:qn");
9ae3a8
+        c = getopt(argc, argv, "hf:O:B:ce6o:s:S:pt:T:qn");
9ae3a8
         if (c == -1) {
9ae3a8
             break;
9ae3a8
         }
9ae3a8
@@ -1239,6 +1264,9 @@ static int img_convert(int argc, char **argv)
9ae3a8
         case 't':
9ae3a8
             cache = optarg;
9ae3a8
             break;
9ae3a8
+        case 'T':
9ae3a8
+            src_cache = optarg;
9ae3a8
+            break;
9ae3a8
         case 'q':
9ae3a8
             quiet = true;
9ae3a8
             break;
9ae3a8
@@ -1275,6 +1303,13 @@ static int img_convert(int argc, char **argv)
9ae3a8
         goto out;
9ae3a8
     }
9ae3a8
 
9ae3a8
+    src_flags = BDRV_O_FLAGS;
9ae3a8
+    ret = bdrv_parse_cache_flags(src_cache, &src_flags);
9ae3a8
+    if (ret < 0) {
9ae3a8
+        error_report("Invalid source cache option: %s", src_cache);
9ae3a8
+        goto out;
9ae3a8
+    }
9ae3a8
+
9ae3a8
     qemu_progress_print(0, 100);
9ae3a8
 
9ae3a8
     bs = g_malloc0(bs_n * sizeof(BlockDriverState *));
9ae3a8
@@ -1283,7 +1318,7 @@ static int img_convert(int argc, char **argv)
9ae3a8
     for (bs_i = 0; bs_i < bs_n; bs_i++) {
9ae3a8
         char *id = bs_n > 1 ? g_strdup_printf("source %d", bs_i)
9ae3a8
                             : g_strdup("source");
9ae3a8
-        bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, BDRV_O_FLAGS,
9ae3a8
+        bs[bs_i] = bdrv_new_open(id, argv[optind + bs_i], fmt, src_flags,
9ae3a8
                                  true, quiet);
9ae3a8
         g_free(id);
9ae3a8
         if (!bs[bs_i]) {
9ae3a8
@@ -2197,8 +2232,8 @@ static int img_rebase(int argc, char **argv)
9ae3a8
     BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
9ae3a8
     BlockDriver *old_backing_drv, *new_backing_drv;
9ae3a8
     char *filename;
9ae3a8
-    const char *fmt, *cache, *out_basefmt, *out_baseimg;
9ae3a8
-    int c, flags, ret;
9ae3a8
+    const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg;
9ae3a8
+    int c, flags, src_flags, ret;
9ae3a8
     int unsafe = 0;
9ae3a8
     int progress = 0;
9ae3a8
     bool quiet = false;
9ae3a8
@@ -2207,10 +2242,11 @@ static int img_rebase(int argc, char **argv)
9ae3a8
     /* Parse commandline parameters */
9ae3a8
     fmt = NULL;
9ae3a8
     cache = BDRV_DEFAULT_CACHE;
9ae3a8
+    src_cache = BDRV_DEFAULT_CACHE;
9ae3a8
     out_baseimg = NULL;
9ae3a8
     out_basefmt = NULL;
9ae3a8
     for(;;) {
9ae3a8
-        c = getopt(argc, argv, "uhf:F:b:pt:q");
9ae3a8
+        c = getopt(argc, argv, "hf:F:b:upt:T:q");
9ae3a8
         if (c == -1) {
9ae3a8
             break;
9ae3a8
         }
9ae3a8
@@ -2237,6 +2273,9 @@ static int img_rebase(int argc, char **argv)
9ae3a8
         case 't':
9ae3a8
             cache = optarg;
9ae3a8
             break;
9ae3a8
+        case 'T':
9ae3a8
+            src_cache = optarg;
9ae3a8
+            break;
9ae3a8
         case 'q':
9ae3a8
             quiet = true;
9ae3a8
             break;
9ae3a8
@@ -2262,6 +2301,13 @@ static int img_rebase(int argc, char **argv)
9ae3a8
         return -1;
9ae3a8
     }
9ae3a8
 
9ae3a8
+    src_flags = BDRV_O_FLAGS;
9ae3a8
+    ret = bdrv_parse_cache_flags(src_cache, &src_flags);
9ae3a8
+    if (ret < 0) {
9ae3a8
+        error_report("Invalid source cache option: %s", src_cache);
9ae3a8
+        return -1;
9ae3a8
+    }
9ae3a8
+
9ae3a8
     /*
9ae3a8
      * Open the images.
9ae3a8
      *
9ae3a8
@@ -2305,7 +2351,7 @@ static int img_rebase(int argc, char **argv)
9ae3a8
 
9ae3a8
         bs_old_backing = bdrv_new("old_backing", &error_abort);
9ae3a8
         bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
9ae3a8
-        ret = bdrv_open(bs_old_backing, backing_name, NULL, BDRV_O_FLAGS,
9ae3a8
+        ret = bdrv_open(bs_old_backing, backing_name, NULL, src_flags,
9ae3a8
                         old_backing_drv, &local_err);
9ae3a8
         if (ret) {
9ae3a8
             error_report("Could not open old backing file '%s': %s",
9ae3a8
@@ -2315,7 +2361,7 @@ static int img_rebase(int argc, char **argv)
9ae3a8
         }
9ae3a8
         if (out_baseimg[0]) {
9ae3a8
             bs_new_backing = bdrv_new("new_backing", &error_abort);
9ae3a8
-            ret = bdrv_open(bs_new_backing, out_baseimg, NULL, BDRV_O_FLAGS,
9ae3a8
+            ret = bdrv_open(bs_new_backing, out_baseimg, NULL, src_flags,
9ae3a8
                         new_backing_drv, &local_err);
9ae3a8
             if (ret) {
9ae3a8
                 error_report("Could not open new backing file '%s': %s",
9ae3a8
diff --git a/qemu-img.texi b/qemu-img.texi
9ae3a8
index 7c28759..3d06e91 100644
9ae3a8
--- a/qemu-img.texi
9ae3a8
+++ b/qemu-img.texi
9ae3a8
@@ -68,6 +68,9 @@ down to the nearest 512 bytes. You may use the common size suffixes like
9ae3a8
 specifies the cache mode that should be used with the (destination) file. See
9ae3a8
 the documentation of the emulator's @code{-drive cache=...} option for allowed
9ae3a8
 values.
9ae3a8
+@item -T @var{src_cache}
9ae3a8
+in contrast specifies the cache mode that should be used with the source
9ae3a8
+file(s).
9ae3a8
 @end table
9ae3a8
 
9ae3a8
 Parameters to snapshot subcommand:
9ae3a8
@@ -109,7 +112,7 @@ Skip the creation of the target volume
9ae3a8
 Command description:
9ae3a8
 
9ae3a8
 @table @option
9ae3a8
-@item check [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] @var{filename}
9ae3a8
+@item check [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
9ae3a8
 
9ae3a8
 Perform a consistency check on the disk image @var{filename}. The command can
9ae3a8
 output in the format @var{ofmt} which is either @code{human} or @code{json}.
9ae3a8
@@ -145,7 +148,7 @@ the backing file, the backing file will not be truncated.  If you want the
9ae3a8
 backing file to match the size of the smaller snapshot, you can safely truncate
9ae3a8
 it yourself once the commit operation successfully completes.
9ae3a8
 
9ae3a8
-@item compare [-f @var{fmt}] [-F @var{fmt}] [-p] [-s] [-q] @var{filename1} @var{filename2}
9ae3a8
+@item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-s] [-q] @var{filename1} @var{filename2}
9ae3a8
 
9ae3a8
 Check if two images have the same content. You can compare images with
9ae3a8
 different format or settings.
9ae3a8
@@ -186,7 +189,7 @@ Error on reading data
9ae3a8
 
9ae3a8
 @end table
9ae3a8
 
9ae3a8
-@item convert [-c] [-p] [-n] [-f @var{fmt}] [-t @var{cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
9ae3a8
+@item convert [-c] [-p] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_name}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
9ae3a8
 
9ae3a8
 Convert the disk image @var{filename} or a snapshot @var{snapshot_name} to disk image @var{output_filename}
9ae3a8
 using format @var{output_fmt}. It can be optionally compressed (@code{-c}
9ae3a8
@@ -298,7 +301,7 @@ source code.
9ae3a8
 
9ae3a8
 List, apply, create or delete snapshots in image @var{filename}.
9ae3a8
 
9ae3a8
-@item rebase [-f @var{fmt}] [-t @var{cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
9ae3a8
+@item rebase [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
9ae3a8
 
9ae3a8
 Changes the backing file of an image. Only the formats @code{qcow2} and
9ae3a8
 @code{qed} support changing the backing file.
9ae3a8
@@ -309,6 +312,9 @@ The backing file is changed to @var{backing_file} and (if the image format of
9ae3a8
 string), then the image is rebased onto no backing file (i.e. it will exist
9ae3a8
 independently of any backing file).
9ae3a8
 
9ae3a8
+@var{cache} specifies the cache mode to be used for @var{filename}, whereas
9ae3a8
+@var{src_cache} specifies the cache mode for reading the new backing file.
9ae3a8
+
9ae3a8
 There are two different modes in which @code{rebase} can operate:
9ae3a8
 @table @option
9ae3a8
 @item Safe mode
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8