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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.