From: "Denis V. Lunev" <den@openvz.org>
Cc: Kevin Wolf <kwolf@redhat.com>, "Denis V. Lunev" <den@openvz.org>,
Jeff Cody <jcody@redhat.com>,
qemu-devel@nongnu.org, Stefan Hajnoczi <stefanha@redhat.com>
Subject: [Qemu-devel] [PATCH 14/16] block/parallels: introduce ParallelsSnapshot data structure
Date: Mon, 15 Dec 2014 11:27:59 +0300 [thread overview]
Message-ID: <1418632081-20667-15-git-send-email-den@openvz.org> (raw)
In-Reply-To: <1418632081-20667-1-git-send-email-den@openvz.org>
In order to support snapshots of parallels images we should maintain
snapshots list in BDRVParallelsState. Snapshots actually forms tree.
Though, in read-only case, we do need to traverse only from current
snapshot leaf to the snapshot tree root. Thus interesting for us
snapshots forms old good linked list.
This patch just introduces the structure for this and fills it with
a signle image as was done before.
True parsing be done in the next patch.
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Jeff Cody <jcody@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
---
block/parallels.c | 110 ++++++++++++++++++++++++++++++++++++------------------
1 file changed, 73 insertions(+), 37 deletions(-)
diff --git a/block/parallels.c b/block/parallels.c
index 0c0e669..d1b52f3 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -56,15 +56,22 @@ struct parallels_header {
char padding[12];
} QEMU_PACKED;
-typedef struct BDRVParallelsState {
- CoMutex lock;
+typedef struct ParallelsSnapshot {
+ BlockDriverState *file;
uint32_t *catalog_bitmap;
unsigned int catalog_size;
unsigned int tracks;
-
unsigned int off_multiplier;
+} ParallelsSnapshot;
+
+typedef struct BDRVParallelsState {
+ CoMutex lock;
+
+ ParallelsSnapshot *snaps;
+ unsigned int snaps_count;
+
unsigned int padding;
} BDRVParallelsState;
@@ -101,49 +108,37 @@ static int parallels_probe(const uint8_t *buf, int buf_size, const char *filenam
return parallels_probe_xml(buf, buf_size);
}
-static int parallels_open_image(BlockDriverState *bs, Error **errp)
+static int parallels_open_image(ParallelsSnapshot *s, int64_t *total_sectors,
+ Error **errp)
{
- BDRVParallelsState *s = bs->opaque;
int i;
struct parallels_header ph;
int ret;
- int64_t total_sectors;
-
- bs->read_only = 1; // no write support yet
- ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph));
+ ret = bdrv_pread(s->file, 0, &ph, sizeof(ph));
if (ret < 0) {
- goto fail;
+ return ret;
}
- total_sectors = le64_to_cpu(ph.nb_sectors);
+ *total_sectors = le64_to_cpu(ph.nb_sectors);
if (le32_to_cpu(ph.version) != HEADER_VERSION) {
goto fail_format;
}
if (!memcmp(ph.magic, HEADER_MAGIC, 16)) {
s->off_multiplier = 1;
- total_sectors = 0xffffffff & total_sectors;
+ *total_sectors = 0xffffffff & *total_sectors;
} else if (!memcmp(ph.magic, HEADER_MAGIC2, 16)) {
s->off_multiplier = le32_to_cpu(ph.tracks);
} else {
goto fail_format;
}
- if (total_sectors == 0) {
+ if (*total_sectors == 0) {
error_setg(errp, "Invalid image: zero total sectors");
ret = -EINVAL;
goto fail;
}
- if (bs->total_sectors == 0) {
- /* no descriptor file, standalone image opened */
- bs->total_sectors = total_sectors;
- }
- if (bs->total_sectors != total_sectors) {
- error_setg(errp, "Invalid image: wrong total sectors");
- ret = -EINVAL;
- goto fail;
- }
s->tracks = le32_to_cpu(ph.tracks);
if (s->tracks == 0) {
@@ -169,7 +164,7 @@ static int parallels_open_image(BlockDriverState *bs, Error **errp)
goto fail;
}
- ret = bdrv_pread(bs->file, 64, s->catalog_bitmap, s->catalog_size * 4);
+ ret = bdrv_pread(s->file, 64, s->catalog_bitmap, s->catalog_size * 4);
if (ret < 0) {
goto fail;
}
@@ -177,7 +172,6 @@ static int parallels_open_image(BlockDriverState *bs, Error **errp)
for (i = 0; i < s->catalog_size; i++)
le32_to_cpus(&s->catalog_bitmap[i]);
- qemu_co_mutex_init(&s->lock);
return 0;
fail_format:
@@ -331,19 +325,25 @@ static int parallels_open_xml(BlockDriverState *bs, int flags, Error **errp)
goto done;
}
+ s->snaps_count = size;
+ s->snaps = g_malloc0(sizeof(ParallelsSnapshot) * s->snaps_count);
+
path_combine(image_path, sizeof(image_path), bs->file->filename, data);
- /* the caller (top layer bdrv_open) will close file for us if bs->file
- is changed. */
- bs->file = NULL;
- ret = bdrv_open(&bs->file, image_path, NULL, NULL, flags | BDRV_O_PROTOCOL,
- NULL, &local_err);
+ ret = bdrv_open(&s->snaps[0].file, image_path, NULL, NULL,
+ flags | BDRV_O_PROTOCOL, NULL, &local_err);
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not open '%s': %s",
image_path, error_get_pretty(local_err));
error_free(local_err);
} else {
- ret = parallels_open_image(bs, errp);
+ int64_t total_sectors;
+ ret = parallels_open_image(s->snaps, &total_sectors, errp);
+ if (bs->total_sectors != total_sectors) {
+ error_setg(errp, "Invalid image: wrong total sectors");
+ ret = -EINVAL;
+ goto done;
+ }
}
done:
@@ -367,17 +367,25 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
uint8_t buf[MAX(1024, HEADER_SIZE)];
int size;
const struct parallels_header *ph;
+ BDRVParallelsState *s = bs->opaque;
size = bdrv_pread(bs->file, 0, buf, sizeof(buf));
if (size < 0) {
return size;
}
+ qemu_co_mutex_init(&s->lock);
+ bs->read_only = 1;
+
ph = (const struct parallels_header *)buf;
if ((!memcmp(ph->magic, HEADER_MAGIC, 16) ||
!memcmp(ph->magic, HEADER_MAGIC2, 16)) &&
le32_to_cpu(ph->version) == HEADER_VERSION) {
- return parallels_open_image(bs, errp);
+ s->snaps_count = 1;
+ s->snaps = g_malloc0(sizeof(ParallelsSnapshot));
+ s->snaps->file = bs->file;
+ bdrv_ref(bs->file);
+ return parallels_open_image(s->snaps, &bs->total_sectors, errp);
} else if (parallels_probe_xml(buf, (unsigned)size)) {
#if CONFIG_LIBXML2
return parallels_open_xml(bs, flags, errp);
@@ -389,10 +397,14 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
}
-static int64_t seek_to_sector(BDRVParallelsState *s, int64_t sector_num)
+static int64_t seek_to_sector(ParallelsSnapshot *s, int64_t sector_num)
{
uint32_t index, offset;
+ if (s == NULL) {
+ return -1;
+ }
+
index = sector_num / s->tracks;
offset = sector_num % s->tracks;
@@ -405,10 +417,27 @@ static int64_t seek_to_sector(BDRVParallelsState *s, int64_t sector_num)
static int cluster_remainder(BDRVParallelsState *s, int64_t sector_num,
int nb_sectors)
{
- int ret = s->tracks - sector_num % s->tracks;
+ int ret = s->snaps->tracks - sector_num % s->snaps->tracks;
return MIN(nb_sectors, ret);
}
+static ParallelsSnapshot *find_snap(BDRVParallelsState *s, int64_t sector_num)
+{
+ int snap_idx;
+ uint32_t index = sector_num / s->snaps->tracks;
+
+ for (snap_idx = 0; snap_idx < s->snaps_count; snap_idx++) {
+ ParallelsSnapshot *snap = s->snaps + snap_idx;
+
+ if (index >= snap->catalog_size || snap->catalog_bitmap[index] == 0) {
+ continue;
+ }
+ return snap;
+ }
+
+ return NULL;
+}
+
static int64_t coroutine_fn parallels_co_get_block_status(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, int *pnum)
{
@@ -416,7 +445,7 @@ static int64_t coroutine_fn parallels_co_get_block_status(BlockDriverState *bs,
int64_t offset;
qemu_co_mutex_lock(&s->lock);
- offset = seek_to_sector(s, sector_num);
+ offset = seek_to_sector(find_snap(s, sector_num), sector_num);
qemu_co_mutex_unlock(&s->lock);
*pnum = cluster_remainder(s, sector_num, nb_sectors);
@@ -437,10 +466,11 @@ static int parallels_read(BlockDriverState *bs, int64_t sector_num,
sector_num += s->padding;
while (nb_sectors > 0) {
- int64_t position = seek_to_sector(s, sector_num);
+ ParallelsSnapshot *snap = find_snap(s, sector_num);
+ int64_t position = seek_to_sector(snap, sector_num);
int n = cluster_remainder(s, sector_num, nb_sectors);
if (position >= 0) {
- int ret = bdrv_read(bs->file, position, buf, n);
+ int ret = bdrv_read(snap->file, position, buf, n);
if (ret < 0) {
return ret;
}
@@ -472,8 +502,14 @@ static coroutine_fn int parallels_co_read(BlockDriverState *bs, int64_t sector_n
static void parallels_close(BlockDriverState *bs)
{
+ int i;
BDRVParallelsState *s = bs->opaque;
- g_free(s->catalog_bitmap);
+
+ for (i = 0; i < s->snaps_count; i++) {
+ ParallelsSnapshot *snap = s->snaps + i;
+ g_free(snap->catalog_bitmap);
+ bdrv_unref(snap->file);
+ }
}
static BlockDriver bdrv_parallels = {
--
1.9.1
next prev parent reply other threads:[~2014-12-15 9:10 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-15 8:27 [Qemu-devel] [PATCH v4 0/16] parallels format support improvements Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 01/16] configure: add dependency from libxml2 Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 02/16] block/parallels: allow to specify DiskDescriptor.xml instead of image file Denis V. Lunev
2014-12-15 10:45 ` Kevin Wolf
2014-12-15 11:51 ` Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 03/16] iotests, parallels: quote TEST_IMG in 076 test to be path-safe Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 04/16] iotests: simple parallels XML disk descriptor file test added Denis V. Lunev
2014-12-15 10:49 ` Kevin Wolf
2014-12-15 8:27 ` [Qemu-devel] [PATCH 05/16] block/parallels: support padded Parallels images Denis V. Lunev
2014-12-15 11:05 ` Kevin Wolf
2014-12-15 11:33 ` Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 06/16] iotests: padded parallels image test Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 07/16] parallels: change copyright information in the image header Denis V. Lunev
2014-12-15 11:06 ` Kevin Wolf
2014-12-15 11:52 ` Denis V. Lunev
2014-12-16 16:29 ` Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 08/16] block/parallels: switch to bdrv_read Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 09/16] block/parallels: read up to cluster end in one go Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 10/16] block/parallels: add get_block_status Denis V. Lunev
2014-12-15 11:52 ` Denis V. Lunev
2014-12-15 12:18 ` Kevin Wolf
2014-12-15 8:27 ` [Qemu-devel] [PATCH 11/16] block/parallels: add support for backing files Denis V. Lunev
2014-12-15 12:30 ` Kevin Wolf
2014-12-15 13:08 ` Roman Kagan
2014-12-15 8:27 ` [Qemu-devel] [PATCH 12/16] iotests: testcase for backing in parallels format Denis V. Lunev
2014-12-15 8:27 ` [Qemu-devel] [PATCH 13/16] block/parallels: read disk size from XML if DiskDescriptor.xml is passed Denis V. Lunev
2014-12-15 12:38 ` Kevin Wolf
2014-12-15 8:27 ` Denis V. Lunev [this message]
2014-12-15 12:45 ` [Qemu-devel] [PATCH 14/16] block/parallels: introduce ParallelsSnapshot data structure Kevin Wolf
2014-12-15 13:32 ` Denis V. Lunev
2014-12-17 16:15 ` [Qemu-devel] [RFC PATCH 1/1] block/parallels: new concept for DiskDescriptor.xml Denis V. Lunev
2014-12-15 8:28 ` [Qemu-devel] [PATCH 15/16] block/parallels: support read-only parallels snapshots Denis V. Lunev
2014-12-15 8:28 ` [Qemu-devel] [PATCH 16/16] iotests: testcase parallels image with snapshots Denis V. Lunev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1418632081-20667-15-git-send-email-den@openvz.org \
--to=den@openvz.org \
--cc=jcody@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).