[PATCH v4 1/4] block: support compressed write at generic layer

2019-10-16 Thread Andrey Shinkevich
To inform the block layer about writing all the data compressed, we
introduce the 'compress' command line option. Based on that option, the
written data will be aligned by the cluster size at the generic layer.

Suggested-by: Roman Kagan 
Suggested-by: Vladimir Sementsov-Ogievskiy 
Signed-off-by: Andrey Shinkevich 
---
 block.c   | 20 +++-
 block/io.c| 14 ++
 block/qcow2.c |  4 
 blockdev.c|  9 -
 include/block/block.h |  1 +
 include/block/block_int.h |  2 ++
 qapi/block-core.json  |  6 +-
 qemu-options.hx   |  6 --
 8 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/block.c b/block.c
index 1946fc6..a674920 100644
--- a/block.c
+++ b/block.c
@@ -1418,6 +1418,11 @@ QemuOptsList bdrv_runtime_opts = {
 .type = QEMU_OPT_BOOL,
 .help = "always accept other writers (default: off)",
 },
+{
+.name = BDRV_OPT_COMPRESS,
+.type = QEMU_OPT_BOOL,
+.help = "compress all writes to the image (default: off)",
+},
 { /* end of list */ }
 },
 };
@@ -1545,6 +1550,14 @@ static int bdrv_open_common(BlockDriverState *bs, 
BlockBackend *file,
 }
 pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), bs->filename);
 
+if (bs->all_write_compressed && !drv->bdrv_co_pwritev_compressed_part) {
+error_setg(errp, "Compression is not supported for the driver '%s'",
+   drv->format_name);
+bs->all_write_compressed = false;
+ret = -ENOTSUP;
+goto fail_opts;
+}
+
 /* Open the image, either directly or using a protocol */
 open_flags = bdrv_open_flags(bs, bs->open_flags);
 node_name = qemu_opt_get(opts, "node-name");
@@ -2983,6 +2996,11 @@ static BlockDriverState *bdrv_open_inherit(const char 
*filename,
 flags &= ~BDRV_O_RDWR;
 }
 
+if (!g_strcmp0(qdict_get_try_str(options, BDRV_OPT_COMPRESS), "on") ||
+qdict_get_try_bool(options, BDRV_OPT_COMPRESS, false)) {
+bs->all_write_compressed = true;
+}
+
 if (flags & BDRV_O_SNAPSHOT) {
 snapshot_options = qdict_new();
 bdrv_temp_snapshot_options(&snapshot_flags, snapshot_options,
@@ -3208,7 +3226,7 @@ static int bdrv_reset_options_allowed(BlockDriverState 
*bs,
  * in bdrv_reopen_prepare() so they can be left out of @new_opts */
 const char *const common_options[] = {
 "node-name", "discard", "cache.direct", "cache.no-flush",
-"read-only", "auto-read-only", "detect-zeroes", NULL
+"read-only", "auto-read-only", "detect-zeroes", "compress", NULL
 };
 
 for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) {
diff --git a/block/io.c b/block/io.c
index f0b86c1..3743a13 100644
--- a/block/io.c
+++ b/block/io.c
@@ -1360,9 +1360,15 @@ static int coroutine_fn 
bdrv_co_do_copy_on_readv(BdrvChild *child,
 /* This does not change the data on the disk, it is not
  * necessary to flush even in cache=writethrough mode.
  */
-ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
-  &local_qiov, 0,
-  BDRV_REQ_WRITE_UNCHANGED);
+if (bs->all_write_compressed) {
+ret = bdrv_driver_pwritev_compressed(bs, cluster_offset,
+ pnum, &local_qiov,
+ qiov_offset);
+} else {
+ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
+  &local_qiov, 0,
+  BDRV_REQ_WRITE_UNCHANGED);
+}
 }
 
 if (ret < 0) {
@@ -1954,7 +1960,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild 
*child,
 } else if (flags & BDRV_REQ_ZERO_WRITE) {
 bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
 ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
-} else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
+} else if (flags & BDRV_REQ_WRITE_COMPRESSED || bs->all_write_compressed) {
 ret = bdrv_driver_pwritev_compressed(bs, offset, bytes,
  qiov, qiov_offset);
 } else if (bytes <= max_transfer) {
diff --git a/block/qcow2.c b/block/qcow2.c
index 7961c05..6b29e16 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1787,6 +1787,10 @@ static void qcow2_refresh_limits(BlockDriverState *bs, 
Error **errp)
 /* Encryption works on a sector granularity */
 bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
 }
+if (bs->all_write_compressed) {
+bs->bl.request_alignment = MAX(bs->bl.request_alignment,
+   s->cluster_size);
+}
 bs->bl.pw

Re: [PATCH v4 1/4] block: support compressed write at generic layer

2019-10-17 Thread Vladimir Sementsov-Ogievskiy
16.10.2019 19:28, Andrey Shinkevich wrote:
> To inform the block layer about writing all the data compressed, we
> introduce the 'compress' command line option. Based on that option, the
> written data will be aligned by the cluster size at the generic layer.
> 
> Suggested-by: Roman Kagan 
> Suggested-by: Vladimir Sementsov-Ogievskiy 
> Signed-off-by: Andrey Shinkevich 
> ---
>   block.c   | 20 +++-
>   block/io.c| 14 ++
>   block/qcow2.c |  4 
>   blockdev.c|  9 -
>   include/block/block.h |  1 +
>   include/block/block_int.h |  2 ++
>   qapi/block-core.json  |  6 +-
>   qemu-options.hx   |  6 --
>   8 files changed, 53 insertions(+), 9 deletions(-)
> 
> diff --git a/block.c b/block.c
> index 1946fc6..a674920 100644
> --- a/block.c
> +++ b/block.c
> @@ -1418,6 +1418,11 @@ QemuOptsList bdrv_runtime_opts = {
>   .type = QEMU_OPT_BOOL,
>   .help = "always accept other writers (default: off)",
>   },
> +{
> +.name = BDRV_OPT_COMPRESS,
> +.type = QEMU_OPT_BOOL,
> +.help = "compress all writes to the image (default: off)",
> +},
>   { /* end of list */ }
>   },
>   };
> @@ -1545,6 +1550,14 @@ static int bdrv_open_common(BlockDriverState *bs, 
> BlockBackend *file,
>   }
>   pstrcpy(bs->exact_filename, sizeof(bs->exact_filename), bs->filename);
>   
> +if (bs->all_write_compressed && !drv->bdrv_co_pwritev_compressed_part) {
> +error_setg(errp, "Compression is not supported for the driver '%s'",
> +   drv->format_name);
> +bs->all_write_compressed = false;
> +ret = -ENOTSUP;
> +goto fail_opts;
> +}
> +
>   /* Open the image, either directly or using a protocol */
>   open_flags = bdrv_open_flags(bs, bs->open_flags);
>   node_name = qemu_opt_get(opts, "node-name");
> @@ -2983,6 +2996,11 @@ static BlockDriverState *bdrv_open_inherit(const char 
> *filename,
>   flags &= ~BDRV_O_RDWR;
>   }
>   
> +if (!g_strcmp0(qdict_get_try_str(options, BDRV_OPT_COMPRESS), "on") ||
> +qdict_get_try_bool(options, BDRV_OPT_COMPRESS, false)) {
> +bs->all_write_compressed = true;
> +}
> +
>   if (flags & BDRV_O_SNAPSHOT) {
>   snapshot_options = qdict_new();
>   bdrv_temp_snapshot_options(&snapshot_flags, snapshot_options,
> @@ -3208,7 +3226,7 @@ static int bdrv_reset_options_allowed(BlockDriverState 
> *bs,
>* in bdrv_reopen_prepare() so they can be left out of @new_opts */
>   const char *const common_options[] = {
>   "node-name", "discard", "cache.direct", "cache.no-flush",
> -"read-only", "auto-read-only", "detect-zeroes", NULL
> +"read-only", "auto-read-only", "detect-zeroes", "compress", NULL
>   };
>   
>   for (e = qdict_first(bs->options); e; e = qdict_next(bs->options, e)) {
> diff --git a/block/io.c b/block/io.c
> index f0b86c1..3743a13 100644
> --- a/block/io.c
> +++ b/block/io.c
> @@ -1360,9 +1360,15 @@ static int coroutine_fn 
> bdrv_co_do_copy_on_readv(BdrvChild *child,
>   /* This does not change the data on the disk, it is not
>* necessary to flush even in cache=writethrough mode.
>*/
> -ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
> -  &local_qiov, 0,
> -  BDRV_REQ_WRITE_UNCHANGED);
> +if (bs->all_write_compressed) {
> +ret = bdrv_driver_pwritev_compressed(bs, cluster_offset,
> + pnum, &local_qiov,
> + qiov_offset);

last argument must be 0, we are using local_qiov, so, it's qiov_offset is 0.

> +} else {
> +ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
> +  &local_qiov, 0,
> +  BDRV_REQ_WRITE_UNCHANGED);
> +}
>   }
>   
>   if (ret < 0) {
> @@ -1954,7 +1960,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild 
> *child,
>   } else if (flags & BDRV_REQ_ZERO_WRITE) {
>   bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
>   ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
> -} else if (flags & BDRV_REQ_WRITE_COMPRESSED) {
> +} else if (flags & BDRV_REQ_WRITE_COMPRESSED || 
> bs->all_write_compressed) {
>   ret = bdrv_driver_pwritev_compressed(bs, offset, bytes,
>qiov, qiov_offset);
>   } else if (bytes <= max_transfer) {
> diff --git a/block/qcow2.c b/block/qcow2.c
> index 7961c05..6b29e16 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -1787,6 +1787,10 @@