From: Uri Lublin <uril@redhat.com>
To: qemu-devel@nongnu.org
Cc: Uri Lublin <uril@redhat.com>
Subject: [Qemu-devel] [PATCH 09/14] block-qcow2: keep highest alloc offset in a qcow2 extension
Date: Tue, 17 Mar 2009 22:40:47 +0200 [thread overview]
Message-ID: <1237322452-11337-10-git-send-email-uril@redhat.com> (raw)
In-Reply-To: <1237322452-11337-9-git-send-email-uril@redhat.com>
Write it upon qcow_create.
Read it upon qcow_open.
Update (if changed and an extension already exists) upon qcow_close.
This makes highest allocated offset statistic more accurate.
Signed-off-by: Uri Lublin <uril@redhat.com>
---
block-qcow2.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 96 insertions(+), 5 deletions(-)
diff --git a/block-qcow2.c b/block-qcow2.c
index 53364ff..ed84a56 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -85,6 +85,7 @@ typedef struct {
} QCowExtension;
#define QCOW_EXT_MAGIC_END 0
#define QCOW_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
+#define QCOW_EXT_MAGIC_HIGH_ALLOC 0xE2792ACB
typedef struct __attribute__((packed)) QCowSnapshotHeader {
@@ -155,6 +156,8 @@ typedef struct BDRVQcowState {
AES_KEY aes_decrypt_key;
int64_t highest_alloc; /* highest cluester allocated (in clusters) */
+ int64_t highest_alloc_old; /* highest-alloc value when image opened */
+ int64_t highest_alloc_offset; /* offset on disk to highest-alloc value */
uint64_t snapshots_offset;
int snapshots_size;
@@ -209,7 +212,8 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
BDRVQcowState *s = bs->opaque;
QCowExtension ext;
uint64_t offset;
-
+ uint64_t high;
+
#ifdef DEBUG_EXT
printf("qcow_read_extensions: start=%ld end=%ld\n", start_offset, end_offset);
#endif
@@ -256,6 +260,24 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
offset += ((ext.len + 7) & ~7);
break;
+ case QCOW_EXT_MAGIC_HIGH_ALLOC:
+ if (ext.len != sizeof(uint64_t)) {
+ fprintf(stderr, "ERROR: ext_high_alloc: len=%u too large"
+ " (>=%lu)\n",
+ ext.len, sizeof(uint64_t));
+ return 2;
+ }
+ if (bdrv_pread(s->hd, offset , &high, ext.len) != ext.len)
+ return 3;
+ s->highest_alloc = be64_to_cpu(high);
+ s->highest_alloc_old = s->highest_alloc;
+ s->highest_alloc_offset = offset;
+#ifdef DEBUG_EXT
+ printf("Qcow2: Got highest_alloc 0x%lu\n", s->highest_alloc);
+#endif
+ offset += ((ext.len + 7) & ~7);
+ break;
+
default:
/* unknown magic -- just skip it */
offset += ((ext.len + 7) & ~7);
@@ -267,6 +289,62 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
}
+static void update_highest_alloc(BlockDriverState *bs)
+{
+ BDRVQcowState *s = bs->opaque;
+ uint64_t high;
+ int ret;
+
+#ifdef DEBUG_EXT
+ QCowExtension ext;
+ int len;
+ char buff[32];
+
+ printf("IN update_highest_alloc for %s: current %lu old %lu offset=%lu\n",
+ bs->filename, s->highest_alloc, s->highest_alloc_old,
+ s->highest_alloc_offset);
+#endif
+
+ if (s->highest_alloc_offset <= 0)
+ return;
+
+ if (s->highest_alloc == s->highest_alloc_old)
+ return;
+
+#ifdef DEBUG_EXT
+ printf("Writing highest_alloc=%lu, was %lu\n",
+ s->highest_alloc, s->highest_alloc_old);
+
+ len = sizeof(ext) + sizeof(uint64_t);
+ ret = bdrv_pread(s->hd, s->highest_alloc_offset - sizeof(uint64_t),
+ buff, len);
+ if (ret != len)
+ fprintf(stderr, "%s: bdrv_pread FAILED (ret=%d expected %d\n",
+ __FUNCTION__, ret, len);
+ if (be32_to_cpu(*(uint32_t*)buff) != QCOW_EXT_MAGIC_HIGH_ALLOC)
+ fprintf(stderr, "%s: offset points to the wrong location (magic)",
+ __FUNCTION__);
+ if (be32_to_cpu(*((uint32_t*)buff + 1)) != sizeof(uint64_t))
+ fprintf(stderr, "%s: offset points to the wrong location (len)",
+ __FUNCTION__);
+ high = be64_to_cpu(*(uint64_t*)(buff + sizeof(ext)));
+ if (high != s->highest_alloc_old)
+ fprintf(stderr, "%s: offset points to the wrong location (value)",
+ __FUNCTION__);
+#endif
+
+ high = cpu_to_be64(s->highest_alloc);
+ ret = bdrv_pwrite(s->hd, s->highest_alloc_offset, &high, sizeof(uint64_t));
+
+#ifdef DEBUG_EXT
+ if (ret != sizeof(uint64_t))
+ fprintf(stderr, "update highest-alloc: bdrv_pwrite FAILED (%d e=%d)\n",
+ ret, (int)sizeof(uint64_t));
+#endif
+}
+
+
+
static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVQcowState *s = bs->opaque;
@@ -363,8 +441,6 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
if (qcow_read_extensions(bs, sizeof(header), ext_end))
goto fail;
- s->highest_alloc = 0;
-
/* read the backing file name */
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
@@ -1509,9 +1585,12 @@ static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
qemu_aio_release(acb);
}
+
static void qcow_close(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
+
+ update_highest_alloc(bs);
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
qemu_free(s->cluster_cache);
@@ -1557,10 +1636,10 @@ static int qcow_create2(const char *filename, int64_t total_size,
int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
int backing_format_len = 0;
QCowHeader header;
- uint64_t tmp, offset;
+ uint64_t tmp, offset, high_alloc;
QCowCreateState s1, *s = &s1;
QCowExtension ext_bf = {0, 0};
-
+ QCowExtension ext_ha = {0, 0};
memset(s, 0, sizeof(*s));
@@ -1572,6 +1651,9 @@ static int qcow_create2(const char *filename, int64_t total_size,
header.version = cpu_to_be32(QCOW_VERSION);
header.size = cpu_to_be64(total_size * 512);
header_size = sizeof(header);
+ ext_ha.magic = QCOW_EXT_MAGIC_HIGH_ALLOC;
+ ext_ha.len = sizeof(uint64_t);
+ header_size += ((sizeof(ext_ha) + ext_ha.len + 7) & ~7);
backing_filename_len = 0;
if (backing_file) {
if (backing_format) {
@@ -1623,6 +1705,15 @@ static int qcow_create2(const char *filename, int64_t total_size,
/* write all the data */
write(fd, &header, sizeof(header));
+
+
+ cpu_to_be32s(&ext_ha.magic);
+ cpu_to_be32s(&ext_ha.len);
+ high_alloc = cpu_to_be64(offset >> s->cluster_bits);
+
+ write(fd, &ext_ha, sizeof(ext_ha));
+ write(fd, &high_alloc, sizeof(uint64_t));
+
if (backing_file) {
if (backing_format_len) {
char zero[16];
--
1.6.0.6
next prev parent reply other threads:[~2009-03-17 20:41 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-03-17 20:40 [Qemu-devel] [PATCH 00/14] block (mostly qcow2) changes (v6) Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 01/14] Introducing qcow2 extensions Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 02/14] block: support known backing format for image create and open Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 03/14] block-qcow2: keep backing file format in a qcow2 extension Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 04/14] qemu-img: adding a "-F base_fmt" option to "qemu-img create -b" Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 05/14] block-qcow2: keep highest allocated offset Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 06/14] block-qcow2: export highest-alloc through BlockDriverInfo and get_info() Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 07/14] block: info blockstats: show highest_allocated if exists Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 08/14] Add a bdrv_close_all() and call it at the end of main() Uri Lublin
2009-03-17 20:40 ` Uri Lublin [this message]
2009-03-17 20:40 ` [Qemu-devel] [PATCH 10/14] qemu-img: info: show highest_alloc if exists Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 11/14] qcow2: qcow_read_extensions: make "advance offset over extension" common Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 12/14] block: pass BDRV_BACKING flag to open of a backing file Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 13/14] block: keep flags an image was opened with Uri Lublin
2009-03-17 20:40 ` [Qemu-devel] [PATCH 14/14] block-qcow2: do not keep track of highest-alloc for backing files Uri Lublin
2009-03-24 11:22 ` [Qemu-devel] [PATCH 00/14] block (mostly qcow2) changes (v6) Gleb Natapov
2009-03-24 11:44 ` Avi Kivity
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=1237322452-11337-10-git-send-email-uril@redhat.com \
--to=uril@redhat.com \
--cc=qemu-devel@nongnu.org \
/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).