Commit 9b80ddf3460f5513b917720a07a1d32ec4ba1817

Authored by aliguori
1 parent 64bf3f4e

Introducing qcow2 extensions (Uri Lublin)

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.

In this patchset, to be used to keep backing file format.

Based on a work done by Shahar Frank <sfrank@redhat.com>.

Signed-off-by: Uri Lublin <uril@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6907 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 72 additions and 0 deletions
block-qcow2.c
... ... @@ -45,6 +45,7 @@
45 45  
46 46 //#define DEBUG_ALLOC
47 47 //#define DEBUG_ALLOC2
  48 +//#define DEBUG_EXT
48 49  
49 50 #define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
50 51 #define QCOW_VERSION 2
... ... @@ -77,6 +78,14 @@ typedef struct QCowHeader {
77 78 uint64_t snapshots_offset;
78 79 } QCowHeader;
79 80  
  81 +
  82 +typedef struct {
  83 + uint32_t magic;
  84 + uint32_t len;
  85 +} QCowExtension;
  86 +#define QCOW_EXT_MAGIC_END 0
  87 +
  88 +
80 89 typedef struct __attribute__((packed)) QCowSnapshotHeader {
81 90 /* header is 8 byte aligned */
82 91 uint64_t l1_table_offset;
... ... @@ -183,11 +192,66 @@ static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
183 192 return 0;
184 193 }
185 194  
  195 +
  196 +/*
  197 + * read qcow2 extension and fill bs
  198 + * start reading from start_offset
  199 + * finish reading upon magic of value 0 or when end_offset reached
  200 + * unknown magic is skipped (future extension this version knows nothing about)
  201 + * return 0 upon success, non-0 otherwise
  202 + */
  203 +static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
  204 + uint64_t end_offset)
  205 +{
  206 + BDRVQcowState *s = bs->opaque;
  207 + QCowExtension ext;
  208 + uint64_t offset;
  209 +
  210 +#ifdef DEBUG_EXT
  211 + printf("qcow_read_extensions: start=%ld end=%ld\n", start_offset, end_offset);
  212 +#endif
  213 + offset = start_offset;
  214 + while (offset < end_offset) {
  215 +
  216 +#ifdef DEBUG_EXT
  217 + /* Sanity check */
  218 + if (offset > s->cluster_size)
  219 + printf("qcow_handle_extension: suspicious offset %lu\n", offset);
  220 +
  221 + printf("attemting to read extended header in offset %lu\n", offset);
  222 +#endif
  223 +
  224 + if (bdrv_pread(s->hd, offset, &ext, sizeof(ext)) != sizeof(ext)) {
  225 + fprintf(stderr, "qcow_handle_extension: ERROR: pread fail from offset %lu\n",
  226 + offset);
  227 + return 1;
  228 + }
  229 + be32_to_cpus(&ext.magic);
  230 + be32_to_cpus(&ext.len);
  231 + offset += sizeof(ext);
  232 +#ifdef DEBUG_EXT
  233 + printf("ext.magic = 0x%x\n", ext.magic);
  234 +#endif
  235 + switch (ext.magic) {
  236 + case QCOW_EXT_MAGIC_END:
  237 + return 0;
  238 + default:
  239 + /* unknown magic -- just skip it */
  240 + offset += ((ext.len + 7) & ~7);
  241 + break;
  242 + }
  243 + }
  244 +
  245 + return 0;
  246 +}
  247 +
  248 +
186 249 static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
187 250 {
188 251 BDRVQcowState *s = bs->opaque;
189 252 int len, i, shift, ret;
190 253 QCowHeader header;
  254 + uint64_t ext_end;
191 255  
192 256 /* Performance is terrible right now with cache=writethrough due mainly
193 257 * to reference count updates. If the user does not explicitly specify
... ... @@ -270,6 +334,14 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
270 334 if (refcount_init(bs) < 0)
271 335 goto fail;
272 336  
  337 + /* read qcow2 extensions */
  338 + if (header.backing_file_offset)
  339 + ext_end = header.backing_file_offset;
  340 + else
  341 + ext_end = s->cluster_size;
  342 + if (qcow_read_extensions(bs, sizeof(header), ext_end))
  343 + goto fail;
  344 +
273 345 /* read the backing file name */
274 346 if (header.backing_file_offset != 0) {
275 347 len = header.backing_file_size;
... ...