diff options
-rw-r--r-- | docs/tools/qemu-img.rst | 6 | ||||
-rw-r--r-- | qemu-img-cmds.hx | 4 | ||||
-rw-r--r-- | qemu-img.c | 26 |
3 files changed, 26 insertions, 10 deletions
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst index ca5a2773cf..4459c065f1 100644 --- a/docs/tools/qemu-img.rst +++ b/docs/tools/qemu-img.rst @@ -667,7 +667,7 @@ Command description: List, apply, create or delete snapshots in image *FILENAME*. -.. option:: rebase [--object OBJECTDEF] [--image-opts] [-U] [-q] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-p] [-u] -b BACKING_FILE [-F BACKING_FMT] FILENAME +.. option:: rebase [--object OBJECTDEF] [--image-opts] [-U] [-q] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-p] [-u] [-c] -b BACKING_FILE [-F BACKING_FMT] FILENAME Changes the backing file of an image. Only the formats ``qcow2`` and ``qed`` support changing the backing file. @@ -694,7 +694,9 @@ Command description: In order to achieve this, any clusters that differ between *BACKING_FILE* and the old backing file of *FILENAME* are merged - into *FILENAME* before actually changing the backing file. + into *FILENAME* before actually changing the backing file. With the + ``-c`` option specified, the clusters which are being merged (but not + the entire *FILENAME* image) are compressed when written. Note that the safe mode is an expensive operation, comparable to converting an image. It only works if the old backing file still diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index 1b1dab5b17..068692d13e 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -88,9 +88,9 @@ SRST ERST DEF("rebase", img_rebase, - "rebase [--object objectdef] [--image-opts] [-U] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename") + "rebase [--object objectdef] [--image-opts] [-U] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] [-c] -b backing_file [-F backing_fmt] filename") SRST -.. option:: rebase [--object OBJECTDEF] [--image-opts] [-U] [-q] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-p] [-u] -b BACKING_FILE [-F BACKING_FMT] FILENAME +.. option:: rebase [--object OBJECTDEF] [--image-opts] [-U] [-q] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-p] [-u] [-c] -b BACKING_FILE [-F BACKING_FMT] FILENAME ERST DEF("resize", img_resize, diff --git a/qemu-img.c b/qemu-img.c index 01de77295e..369c2e8ddf 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -3534,11 +3534,13 @@ static int img_rebase(int argc, char **argv) char *filename; const char *fmt, *cache, *src_cache, *out_basefmt, *out_baseimg; int c, flags, src_flags, ret; + BdrvRequestFlags write_flags = 0; bool writethrough, src_writethrough; int unsafe = 0; bool force_share = false; int progress = 0; bool quiet = false; + bool compress = false; Error *local_err = NULL; bool image_opts = false; int64_t write_align; @@ -3555,9 +3557,10 @@ static int img_rebase(int argc, char **argv) {"object", required_argument, 0, OPTION_OBJECT}, {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, {"force-share", no_argument, 0, 'U'}, + {"compress", no_argument, 0, 'c'}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, ":hf:F:b:upt:T:qU", + c = getopt_long(argc, argv, ":hf:F:b:upt:T:qUc", long_options, NULL); if (c == -1) { break; @@ -3605,6 +3608,9 @@ static int img_rebase(int argc, char **argv) case 'U': force_share = true; break; + case 'c': + compress = true; + break; } } @@ -3657,6 +3663,14 @@ static int img_rebase(int argc, char **argv) unfiltered_bs = bdrv_skip_filters(bs); + if (compress && !block_driver_can_compress(unfiltered_bs->drv)) { + error_report("Compression not supported for this file format"); + ret = -1; + goto out; + } else if (compress) { + write_flags |= BDRV_REQ_WRITE_COMPRESSED; + } + if (out_basefmt != NULL) { if (bdrv_find_format(out_basefmt) == NULL) { error_report("Invalid format name: '%s'", out_basefmt); @@ -3666,18 +3680,18 @@ static int img_rebase(int argc, char **argv) } /* - * We need overlay subcluster size to make sure write requests are - * aligned. + * We need overlay subcluster size (or cluster size in case writes are + * compressed) to make sure write requests are aligned. */ ret = bdrv_get_info(unfiltered_bs, &bdi); if (ret < 0) { error_report("could not get block driver info"); goto out; } else if (bdi.subcluster_size == 0) { - bdi.subcluster_size = 1; + bdi.cluster_size = bdi.subcluster_size = 1; } - write_align = bdi.subcluster_size; + write_align = compress ? bdi.cluster_size : bdi.subcluster_size; /* For safe rebasing we need to compare old and new backing file */ if (!unsafe) { @@ -3930,7 +3944,7 @@ static int img_rebase(int argc, char **argv) } else { assert(written + pnum <= IO_BUF_SIZE); ret = blk_pwrite(blk, offset + written, pnum, - buf_old + written, 0); + buf_old + written, write_flags); } if (ret < 0) { error_report("Error while writing to COW image: %s", |