qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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

  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).