[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 09/14] block-qcow2: keep highest alloc offset in a q
From: |
Uri Lublin |
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 |
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 <address@hidden>
---
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
- [Qemu-devel] [PATCH 00/14] block (mostly qcow2) changes (v6), Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 01/14] Introducing qcow2 extensions, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 02/14] block: support known backing format for image create and open, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 03/14] block-qcow2: keep backing file format in a qcow2 extension, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 04/14] qemu-img: adding a "-F base_fmt" option to "qemu-img create -b", Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 05/14] block-qcow2: keep highest allocated offset, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 06/14] block-qcow2: export highest-alloc through BlockDriverInfo and get_info(), Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 07/14] block: info blockstats: show highest_allocated if exists, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 08/14] Add a bdrv_close_all() and call it at the end of main(), Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 09/14] block-qcow2: keep highest alloc offset in a qcow2 extension,
Uri Lublin <=
- [Qemu-devel] [PATCH 10/14] qemu-img: info: show highest_alloc if exists, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 11/14] qcow2: qcow_read_extensions: make "advance offset over extension" common, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 12/14] block: pass BDRV_BACKING flag to open of a backing file, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 13/14] block: keep flags an image was opened with, Uri Lublin, 2009/03/17
- [Qemu-devel] [PATCH 14/14] block-qcow2: do not keep track of highest-alloc for backing files, Uri Lublin, 2009/03/17
Re: [Qemu-devel] [PATCH 00/14] block (mostly qcow2) changes (v6), Gleb Natapov, 2009/03/24