Features/QED
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 * chunk_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 | +----------+ +----------+
Operations
Read
- If L2 table is not present in L1, read from backing image.
- If data cluster is not present in L2, read from backing image.
- Otherwise read data from cluster.
Write
- If L2 table is not present in L1, allocate new cluster and L2. Perform L2 and L1 link after writing data.
- If data cluster is not present in L2, allocate new cluster. Perform L1 link after writing data.
- Otherwise overwrite data cluster.
Grow
- If table_size * TABLE_NOFFSETS < new_image_size, fail -EOVERFLOW. The L1 table is not big enough.
- Write new image_size header field.