The QCOW Image Format

The QCOW image format is one of the disk image formats supported by the QEMU processor emulator. It is a representation of a fixed size block device in a file. Benefits it offers over using raw dump representation include:

  1. Smaller file size, even on filesystems which don't support holes (i.e. sparse files)
  2. Snapshot support, where the image only represents changes made to an underlying disk image
  3. Optional zlib based compression
  4. Optional AES encryption

The qemu-img command is the most common way of manipulating these images e.g.

  $> qemu-img create -f qcow test.qcow 4G
  Formating 'test.qcow', fmt=qcow, size=4194304 kB
  $> qemu-img convert test.qcow -O raw test.img

The Header

Each QCOW file begins with a header, in big endian format, as follows:

  typedef struct QCowHeader {
      uint32_t magic;
      uint32_t version;

      uint64_t backing_file_offset;
      uint32_t backing_file_size;
      uint32_t mtime;

      uint64_t size; /* in bytes */

      uint8_t  cluster_bits;
      uint8_t  l2_bits;
      uint32_t crypt_method;

      uint64_t l1_table_offset;
  } QCowHeader;

2-Level Lookups

With QCOW, the contents of the device are stored in clusters. Each cluster contains a number of 512 byte sectors.

In order to find the cluster for a given address within the device, you must traverse two levels of tables. The L1 table is an array of file offsets to L2 tables, and each L2 table is an array of file offsets to clusters.

So, an address is split into three separate offsets according to the cluster_bits and l2_bits fields. For example, if cluster_bits is 12 and l2_bits is 9, then the address is split up as follows:

Note, the size of the L1 table is a function of the size of the represented disk image:

 l1_size = ceiling (disk_size / (cluster_size * l2_size))

In other words, in order to map a given disk address to an offset within the image:

  1. Obtain the L1 table address using the l1_table_offset header field
  2. Use the top (64 - l2_bits - cluster_bits) bits of the address to index the L1 table as an array of 64 bit entries
  3. Obtain the L2 table address using the offset in the L1 table
  4. Use the next l2_bits of the address to index the L2 table as an array of 64 bit entries
  5. Obtain the cluster address using the offset in the L2 table. (Assuming the most significant bit of the cluster address is zero. See the details on compression below.)
  6. Use the remaining cluster_bits of the address as an offset within the cluster itself

If the offset found in either the L1 or L2 table is zero, that area of the disk is not allocated within the image.

Snapshots

The QCOW format can represent the notion of a snapshot. That is, a QCOW image can be used to store the changes to another disk image, without actually affecting the contents of the original image.

The representation is very simple. The snapshot image contains the path to the original disk image, and the snapshot image header gives the location of the path string within the file.

When you want to read an area from the snapshot, you first check to see if that area is allocated within the snapshot image. If not, you read the area from the original disk image.

Compression

The QCOW format supports compression by allowing each cluster to be independently compressed with zlib.

This is represented in the cluster offset obtained from the L2 table as follows:

Encryption

The QCOW format also supports the encryption of clusters.

If the crypt_method header field is 1, then a 16 character password is used as the 128 bit AES key.

Each sector within each cluster is independently encrypted using AES Cipher Block Chaining mode, using the sector's offset (relative to the start of the device) in little-endian format as the first 64 bits of the 128 bit initialisation vector.

Mark McLoughlin. June 21, 2006.