aboutsummaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-01-24 15:28:36 +0000
committerPeter Maydell <peter.maydell@linaro.org>2018-01-24 15:28:36 +0000
commit25bfd5a75fa3e8f5796656c7634e26193f7bedc1 (patch)
treee8c02a7393555643add8e3b2f4be6b8a015c7ca8 /block
parent238e2d93c9ddc9bc6b5392289bed38a4ebff004d (diff)
parentbcbb3866da19cce4360c828b6ec1c2a137757927 (diff)
Merge remote-tracking branch 'remotes/stefanha/tags/block-pull-request' into staging
Pull request v2: * Drop merge failure from a previous pull request that broke virtio-blk on ARM guests * Add Parallels XML patch series # gpg: Signature made Mon 22 Jan 2018 16:00:40 GMT # gpg: using RSA key 0x9CA4ABB381AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8 * remotes/stefanha/tags/block-pull-request: block/parallels: add backing support to readv/writev block/parallels: replace some magic numbers block/parallels: move some structures into header configure: add dependency docs/interop/prl-xml: description of Parallels Disk format block: add block_set_io_throttle virtio-blk-pci QMP example Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'block')
-rw-r--r--block/Makefile.objs2
-rw-r--r--block/parallels.c108
-rw-r--r--block/parallels.h88
3 files changed, 138 insertions, 60 deletions
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 6eaf78a046..a73387f1bf 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -47,3 +47,5 @@ block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
dmg-bz2.o-libs := $(BZIP2_LIBS)
qcow.o-libs := -lz
linux-aio.o-libs := -laio
+parallels.o-cflags := $(LIBXML2_CFLAGS)
+parallels.o-libs := $(LIBXML2_LIBS)
diff --git a/block/parallels.c b/block/parallels.c
index 9545761f49..d3802085e3 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -36,6 +36,7 @@
#include "qemu/bswap.h"
#include "qemu/bitmap.h"
#include "migration/blocker.h"
+#include "parallels.h"
/**************************************************************/
@@ -45,30 +46,6 @@
#define HEADER_INUSE_MAGIC (0x746F6E59)
#define MAX_PARALLELS_IMAGE_FACTOR (1ull << 32)
-#define DEFAULT_CLUSTER_SIZE 1048576 /* 1 MiB */
-
-
-// always little-endian
-typedef struct ParallelsHeader {
- char magic[16]; // "WithoutFreeSpace"
- uint32_t version;
- uint32_t heads;
- uint32_t cylinders;
- uint32_t tracks;
- uint32_t bat_entries;
- uint64_t nb_sectors;
- uint32_t inuse;
- uint32_t data_off;
- char padding[12];
-} QEMU_PACKED ParallelsHeader;
-
-
-typedef enum ParallelsPreallocMode {
- PRL_PREALLOC_MODE_FALLOCATE = 0,
- PRL_PREALLOC_MODE_TRUNCATE = 1,
- PRL_PREALLOC_MODE__MAX = 2,
-} ParallelsPreallocMode;
-
static QEnumLookup prealloc_mode_lookup = {
.array = (const char *const[]) {
"falloc",
@@ -77,34 +54,6 @@ static QEnumLookup prealloc_mode_lookup = {
.size = PRL_PREALLOC_MODE__MAX
};
-typedef struct BDRVParallelsState {
- /** Locking is conservative, the lock protects
- * - image file extending (truncate, fallocate)
- * - any access to block allocation table
- */
- CoMutex lock;
-
- ParallelsHeader *header;
- uint32_t header_size;
- bool header_unclean;
-
- unsigned long *bat_dirty_bmap;
- unsigned int bat_dirty_block;
-
- uint32_t *bat_bitmap;
- unsigned int bat_size;
-
- int64_t data_end;
- uint64_t prealloc_size;
- ParallelsPreallocMode prealloc_mode;
-
- unsigned int tracks;
-
- unsigned int off_multiplier;
- Error *migration_blocker;
-} BDRVParallelsState;
-
-
#define PARALLELS_OPT_PREALLOC_MODE "prealloc-mode"
#define PARALLELS_OPT_PREALLOC_SIZE "prealloc-size"
@@ -193,6 +142,7 @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num,
static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
+ int ret;
BDRVParallelsState *s = bs->opaque;
int64_t pos, space, idx, to_allocate, i, len;
@@ -221,7 +171,6 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
return len;
}
if (s->data_end + space > (len >> BDRV_SECTOR_BITS)) {
- int ret;
space += s->prealloc_size;
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
ret = bdrv_pwrite_zeroes(bs->file,
@@ -237,6 +186,37 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
}
}
+ /* Try to read from backing to fill empty clusters
+ * FIXME: 1. previous write_zeroes may be redundant
+ * 2. most of data we read from backing will be rewritten by
+ * parallels_co_writev. On aligned-to-cluster write we do not need
+ * this read at all.
+ * 3. it would be good to combine write of data from backing and new
+ * data into one write call */
+ if (bs->backing) {
+ int64_t nb_cow_sectors = to_allocate * s->tracks;
+ int64_t nb_cow_bytes = nb_cow_sectors << BDRV_SECTOR_BITS;
+ QEMUIOVector qiov;
+ struct iovec iov = {
+ .iov_len = nb_cow_bytes,
+ .iov_base = qemu_blockalign(bs, nb_cow_bytes)
+ };
+ qemu_iovec_init_external(&qiov, &iov, 1);
+
+ ret = bdrv_co_readv(bs->backing, idx * s->tracks, nb_cow_sectors,
+ &qiov);
+ if (ret < 0) {
+ qemu_vfree(iov.iov_base);
+ return ret;
+ }
+
+ ret = bdrv_co_writev(bs->file, s->data_end, nb_cow_sectors, &qiov);
+ qemu_vfree(iov.iov_base);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
for (i = 0; i < to_allocate; i++) {
s->bat_bitmap[idx + i] = cpu_to_le32(s->data_end / s->off_multiplier);
s->data_end += s->tracks;
@@ -360,12 +340,19 @@ static coroutine_fn int parallels_co_readv(BlockDriverState *bs,
nbytes = n << BDRV_SECTOR_BITS;
+ qemu_iovec_reset(&hd_qiov);
+ qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
+
if (position < 0) {
- qemu_iovec_memset(qiov, bytes_done, 0, nbytes);
+ if (bs->backing) {
+ ret = bdrv_co_readv(bs->backing, sector_num, n, &hd_qiov);
+ if (ret < 0) {
+ break;
+ }
+ } else {
+ qemu_iovec_memset(&hd_qiov, 0, 0, nbytes);
+ }
} else {
- qemu_iovec_reset(&hd_qiov);
- qemu_iovec_concat(&hd_qiov, qiov, bytes_done, nbytes);
-
ret = bdrv_co_readv(bs->file, position, n, &hd_qiov);
if (ret < 0) {
break;
@@ -527,8 +514,9 @@ static int parallels_create(const char *filename, QemuOpts *opts, Error **errp)
memcpy(header.magic, HEADER_MAGIC2, sizeof(header.magic));
header.version = cpu_to_le32(HEADER_VERSION);
/* don't care much about geometry, it is not used on image level */
- header.heads = cpu_to_le32(16);
- header.cylinders = cpu_to_le32(total_size / BDRV_SECTOR_SIZE / 16 / 32);
+ header.heads = cpu_to_le32(HEADS_NUMBER);
+ header.cylinders = cpu_to_le32(total_size / BDRV_SECTOR_SIZE
+ / HEADS_NUMBER / SEC_IN_CYL);
header.tracks = cpu_to_le32(cl_size >> BDRV_SECTOR_BITS);
header.bat_entries = cpu_to_le32(bat_entries);
header.nb_sectors = cpu_to_le64(DIV_ROUND_UP(total_size, BDRV_SECTOR_SIZE));
@@ -798,7 +786,7 @@ static BlockDriver bdrv_parallels = {
.bdrv_co_flush_to_os = parallels_co_flush_to_os,
.bdrv_co_readv = parallels_co_readv,
.bdrv_co_writev = parallels_co_writev,
-
+ .supports_backing = true,
.bdrv_create = parallels_create,
.bdrv_check = parallels_check,
.create_opts = &parallels_create_opts,
diff --git a/block/parallels.h b/block/parallels.h
new file mode 100644
index 0000000000..4b044079ef
--- /dev/null
+++ b/block/parallels.h
@@ -0,0 +1,88 @@
+/*
+* Block driver for Parallels disk image format
+*
+* Copyright (c) 2015-2017 Virtuozzo, Inc.
+* Authors:
+* 2016-2017 Klim S. Kireev <klim.kireev@virtuozzo.com>
+* 2015 Denis V. Lunev <den@openvz.org>
+*
+* This code was originally based on comparing different disk images created
+* by Parallels. Currently it is based on opened OpenVZ sources
+* available at
+* https://github.com/OpenVZ/ploop
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*/
+#ifndef BLOCK_PARALLELS_H
+#define BLOCK_PARALLELS_H
+#include "qemu/coroutine.h"
+#include "qemu/typedefs.h"
+
+#define HEADS_NUMBER 16
+#define SEC_IN_CYL 32
+#define DEFAULT_CLUSTER_SIZE 1048576 /* 1 MiB */
+
+/* always little-endian */
+typedef struct ParallelsHeader {
+ char magic[16]; /* "WithoutFreeSpace" */
+ uint32_t version;
+ uint32_t heads;
+ uint32_t cylinders;
+ uint32_t tracks;
+ uint32_t bat_entries;
+ uint64_t nb_sectors;
+ uint32_t inuse;
+ uint32_t data_off;
+ char padding[12];
+} QEMU_PACKED ParallelsHeader;
+
+typedef enum ParallelsPreallocMode {
+ PRL_PREALLOC_MODE_FALLOCATE = 0,
+ PRL_PREALLOC_MODE_TRUNCATE = 1,
+ PRL_PREALLOC_MODE__MAX = 2,
+} ParallelsPreallocMode;
+
+typedef struct BDRVParallelsState {
+ /** Locking is conservative, the lock protects
+ * - image file extending (truncate, fallocate)
+ * - any access to block allocation table
+ */
+ CoMutex lock;
+
+ ParallelsHeader *header;
+ uint32_t header_size;
+ bool header_unclean;
+
+ unsigned long *bat_dirty_bmap;
+ unsigned int bat_dirty_block;
+
+ uint32_t *bat_bitmap;
+ unsigned int bat_size;
+
+ int64_t data_end;
+ uint64_t prealloc_size;
+ ParallelsPreallocMode prealloc_mode;
+
+ unsigned int tracks;
+
+ unsigned int off_multiplier;
+ Error *migration_blocker;
+} BDRVParallelsState;
+
+#endif