[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 01/14] Introducing qcow2 extensions
From: |
Uri Lublin |
Subject: |
[Qemu-devel] [PATCH 01/14] Introducing qcow2 extensions |
Date: |
Tue, 17 Mar 2009 22:40:39 +0200 |
Qcow2 extensions are build of magic (id) len (in bytes) and data.
They reside right after the qcow2 header.
If a backing filename exists it follows the qcow2 extension (if exist)
Qcow2 extensions are read upon image open.
Qcow2 extensions are identified by their magic.
Unknown qcow2 extensions (unknown magic) are skipped.
A Special magic of 0 means end-of-qcow2-extensions.
To be used to keep backing file format, highest allocated offset
and more.
Based on a work done by Shahar Frank <address@hidden>.
Signed-off-by: Uri Lublin <address@hidden>
---
block-qcow2.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/block-qcow2.c b/block-qcow2.c
index afbf7fe..23e66b0 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -45,6 +45,7 @@
//#define DEBUG_ALLOC
//#define DEBUG_ALLOC2
+//#define DEBUG_EXT
#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
#define QCOW_VERSION 2
@@ -77,6 +78,14 @@ typedef struct QCowHeader {
uint64_t snapshots_offset;
} QCowHeader;
+
+typedef struct {
+ uint32_t magic;
+ uint32_t len;
+} QCowExtension;
+#define QCOW_EXT_MAGIC_END 0
+
+
typedef struct __attribute__((packed)) QCowSnapshotHeader {
/* header is 8 byte aligned */
uint64_t l1_table_offset;
@@ -183,11 +192,65 @@ static int qcow_probe(const uint8_t *buf, int buf_size,
const char *filename)
return 0;
}
+
+/* read qcow2 extension and fill bs
+ * start reading from start_offset
+ * finish reading upon magic of value 0 or when end_offset reached
+ * unknown magic is skipped (future extension this version knows nothing about)
+ * return 0 upon success, non-0 otherwise
+ */
+static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
+ uint64_t end_offset)
+{
+ BDRVQcowState *s = bs->opaque;
+ QCowExtension ext;
+ uint64_t offset;
+
+#ifdef DEBUG_EXT
+ printf("qcow_read_extensions: start=%ld end=%ld\n", start_offset,
end_offset);
+#endif
+ offset = start_offset;
+ while (offset < end_offset) {
+
+#ifdef DEBUG_EXT
+ /* Sanity check */
+ if (offset > s->cluster_size)
+ printf("qcow_handle_extension: suspicious offset %lu\n", offset);
+
+ printf("attemting to read extended header in offset %lu\n", offset);
+#endif
+
+ if (bdrv_pread(s->hd, offset, &ext, sizeof(ext)) != sizeof(ext)) {
+ fprintf(stderr, "qcow_handle_extension: ERROR: pread fail from
offset %lu\n",
+ offset);
+ return 1;
+ }
+ be32_to_cpus(&ext.magic);
+ be32_to_cpus(&ext.len);
+ offset += sizeof(ext);
+#ifdef DEBUG_EXT
+ printf("ext.magic = 0x%x\n", ext.magic);
+#endif
+ switch (ext.magic) {
+ case QCOW_EXT_MAGIC_END:
+ return 0;
+ default:
+ /* unknown magic -- just skip it */
+ offset += ((ext.len + 7) & ~7);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVQcowState *s = bs->opaque;
int len, i, shift, ret;
QCowHeader header;
+ uint64_t ext_end;
/* Performance is terrible right now with cache=writethrough due mainly
* to reference count updates. If the user does not explicitly specify
@@ -270,6 +333,14 @@ static int qcow_open(BlockDriverState *bs, const char
*filename, int flags)
if (refcount_init(bs) < 0)
goto fail;
+ /* read qcow2 extensions */
+ if (header.backing_file_offset)
+ ext_end = header.backing_file_offset;
+ else
+ ext_end = s->cluster_size;
+ if (qcow_read_extensions(bs, sizeof(header), ext_end))
+ goto fail;
+
/* read the backing file name */
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
--
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 <=
- [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, 2009/03/17
- [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