Features/QED

From QEMU

Specification

The file format looks like this:

+--------+--------------+---------+---------+-----+
| header | extent table | extent0 | extent1 | ... |
+--------+--------------+---------+---------+-----+

Header

Header {
    uint32_t magic;               /* COW2 */
    uint32_t features;            /* format feature bits */

    uint32_t cluster_size;        /* in bytes */
    uint32_t table_size;          /* table chunk size, in clusters */
    uint64_t l1_table_offset;     /* L1 table offset, in cluster */
    uint64_t image_size;          /* total image size, in clusters */

    uint32_t backing_file_offset; /* in bytes from start of header */
    uint32_t backing_file_size;   /* in bytes */
}

Extent table

#define TABLE_NOFFSETS (table_size * cluster_size / sizeof(uint64_t))
 
Table {
    uint64_t offsets[TABLE_NOFFSETS];
}

The extent tables are organized as follows:

                   +----------+
                   | L1 table |
                   +----------+
              ,------'  |  '------.
         +----------+   |    +----------+
         | L2 table |  ...   | L2 table |
         +----------+        +----------+
     ,------'  |  '------.
+----------+   |    +----------+
|   Data   |  ...   |   Data   |
+----------+        +----------+

The table_size field allows tables to be multiples of the cluster size. For example, cluster_size=64 KB and table_size=4 results in 256 KB tables.

Operations

Read

  1. If L2 table is not present in L1, read from backing image.
  2. If data cluster is not present in L2, read from backing image.
  3. Otherwise read data from cluster.

Write

  1. If L2 table is not present in L1, allocate new cluster and L2. Perform L2 and L1 link after writing data.
  2. If data cluster is not present in L2, allocate new cluster. Perform L1 link after writing data.
  3. Otherwise overwrite data cluster.

Grow

  1. If table_size * TABLE_NOFFSETS < new_image_size, fail -EOVERFLOW. The L1 table is not big enough.
  2. Write new image_size header field.