Filesystems · Flash and Block Layers
Zoned Block Devices and the Zone Append Model
How zone semantics replace the random-write abstraction with explicit sequential-write regions, what append buys, and which costs move from the device to the host.
Everything in the layers below this point exists to preserve one abstraction: a logical block address is a place where the host may write at any time, any number of times. The flash translation layer maintains a mapping table to sustain that fiction, garbage collection reclaims the space the fiction requires, and the resulting write amplification is the price of random writes on a medium that cannot do them. Zoned storage removes the fiction. A zoned device divides its address space into zones and requires writes within a zone to be sequential. In exchange, the device can drop most of the mapping table and the host gains control over the placement decisions that determine amplification.
The zone model
A zoned block device reports a list of zones, each with a start address, a length, and a type. The length is the zone size and is uniform across the device apart from an optional last zone. The types describe what writes are permitted.
A conventional zone accepts random writes, like an ordinary block device. A sequential-write-required zone accepts writes only at its write pointer: a position that starts at the zone’s beginning, advances by the length of each write, and cannot go backwards. A write at the write pointer advances it; a write at any other offset in the zone is rejected. Writing past the end of the zone is an error. To reuse a zone, the host resets it, which discards all of its contents and moves the write pointer back to the start.
The write pointer is readable, either through a report command or through the device’s zone metadata, and it can be discovered at mount time by reading the zones’ states. Position and condition are separate: the write pointer’s offset from the zone start says how much of the zone is written, while the zone’s condition says whether it may be written at all. A specification of the model names conditions such as empty, implicitly open, explicitly open, closed, full, read-only and offline; an explicit open is a resource the host must ask for and release, and the number of zones in an open condition is capped. There is no free-page pool, no invalid page accounting, and no mapping table entry per page.
The three ways a device can expose this are distinguished by who manages the zones. A host-aware device accepts random writes but performs better with sequential ones, and the host may ignore the zone structure. A host-managed device rejects non-sequential writes and the host must respect the model. A host-managed zoned namespace on NVMe, usually called ZNS, is the flash-native case: the namespace is a set of zones, each backed by an erase-block-aligned region of the media, with no mapping table between logical and physical addresses at all.
What the device stops doing
The savings are substantial and specific. A ZNS device does not need a per-page mapping table, so the DRAM that table occupied is either gone or much smaller. It does not perform garbage collection on the host’s behalf, so the host’s writes are programmed exactly once and the write amplification at the device is 1.0 for data that lands in a zone and is never moved. It does not need over-provisioning reserved for collection, so the advertised capacity can be closer to the raw capacity.
Those savings are not free; they are transferred. The host now owns the placement decision, which means the host must know which data is hot, must group data by expected lifetime into zones, and must decide when a zone’s contents are dead and the zone can be reset. A filesystem designed for a zoned device writes sequentially within a zone and allocates new zones for new data rather than overwriting in place. A log-structured design is the natural fit, because it never overwrites in place: it appends to a log and updates an index, which maps directly onto a zone’s write pointer and a reset that discards a segment wholesale.
The result is that the same write amplification appears at a different layer. A host that groups data badly, mixing long-lived and short-lived data in one zone, must copy the long-lived data out before resetting the zone, which is the same collection cost as before, now paid by the host with the host’s CPU and memory bandwidth. The gain comes from doing it with better information: the filesystem knows which blocks belong to which file and when a file is deleted, while the device knows only which addresses were written.
Zone append and the write pointer race
A sequential-write requirement creates a coordination problem. If several threads in the host want to write to the same zone, each must know the current write pointer to compute its write offset, and the pointer advances only after each write completes. Two concurrent writes that both read the pointer before either completes will collide, and one will be rejected. Serializing the writes per zone costs the concurrency that a multi-queue device was built to provide.
Zone append solves this by moving the offset decision to the device. The host submits a write with an offset of zero and a length, and the device places the data at the current write pointer and returns the offset it used in the completion. The host does not need to know the pointer in advance, does not need to serialize, and can submit many appends to the same zone concurrently. The device serializes them internally, which it can do cheaply because it is already arbitrating access to the zone.
The cost is that the host learns the final location only at completion, so any metadata that records where the data went must be updated afterwards. A filesystem that writes a data block and then records its address in an inode must wait for the append’s completion before writing the inode, or must record the address in a later structure. Log-structured designs handle this naturally: the log entry’s position is derivable from the sequence of appends, and the index is updated after the fact.
/* A model of the append path: the host supplies data and a zone, the device
* supplies the offset, and the host learns that offset at completion. */
struct zone_append {
uint64_t zone_id;
void *buf;
size_t len;
uint64_t written_at; /* filled in by the completion, in sectors */
int status;
};
/* Issue the command. The host never computes an offset for an append. */
static int submit_append(int fd, struct zone_append *a)
{
struct append_cmd cmd = {
.zone = a->zone_id,
.buf = a->buf,
.len = a->len,
};
if (write(fd, &cmd, sizeof cmd) != (ssize_t)sizeof cmd)
return -1;
return wait_for_completion(fd, &a->written_at, &a->status);
}
The offset returned is a sector number within the zone, and the caller must convert it to whatever address form its metadata uses. A caller that ignores the returned offset and assumes the append landed where it expected has reintroduced the race it was trying to avoid.
Reset, and the granularity of reclamation
A zone reset is the only operation that frees space. It applies to a whole zone and is all-or-nothing: every block in the zone becomes free and its contents are gone. There is no partial reset, so a zone that holds one live block and 99 percent dead data cannot be reclaimed without moving that block.
This makes zone size the analogue of erase block size, and the same economics apply. A host that packs a zone with data of uniform lifetime can reset it cheaply. A host that mixes lifetimes pays the copy cost of the survivors, exactly as garbage collection does on a conventional device, and the amplification formula is the same one with the zone’s valid fraction in place of the block’s. The difference is that the host can choose the packing, and the choice is visible in the host’s own data structures rather than hidden in firmware.
Zones also have a limit on how many can be open at once, and the limit is a device property reported with the zone list. A host that wants to write to many zones concurrently, one per file or one per stream, may exceed it, and a write to a zone beyond the open limit fails or requires closing another. The limit is typically small relative to the number of zones, on the order of tens to low hundreds, which constrains how finely the host can partition its write streams. A filesystem with many concurrent writers must multiplex them onto a smaller number of open zones, and the multiplexing determines how well lifetimes stay separated.
Where the model breaks down
Zoned devices cannot serve arbitrary workloads. An application that rewrites a small region in place, such as a database’s page cache writeback or a virtual machine’s disk image, has no way to express that on a sequential-write zone without a translation layer above it. The common answer is a host-side translation layer that provides a normal block device on top of zones, performing the same mapping and collection the device used to do. That layer can be more efficient because it sees the workload’s semantics, or less efficient because it has less information about the media than the firmware did.
The second limitation is read amplification of the write pointer. Reading the pointer of a zone that is being written concurrently requires a command that may be serialized against writes, and a host that polls it frequently adds overhead. The append path avoids the poll for writes, but a host that needs to know a zone’s fill level for space accounting still has to ask.
The third is that the model has no partial failure story that differs from a conventional device. A zone reset that is interrupted leaves the zone in a state the host must discover at mount, and the write pointer’s position after an unclean shutdown is not necessarily the last one the host recorded. A host must treat the pointer as authoritative and rebuild its own accounting from it, which is the zoned equivalent of rebuilding a mapping table from page metadata.
The net position of zoned storage in the stack is that it removes a layer of indirection and hands its responsibilities upward. Whether that is a gain depends on whether the layer above has the information to make the placement decisions better than the firmware did. A log-structured filesystem does; a general-purpose one with in-place updates does not, and needs a translation layer that reconstructs what the device gave up.
References
- Zoned Block Commands - 2 (ZBC-2) — T10 / INCITS
- Zoned Namespaces (ZNS) Command Set Specification — NVM Express, Inc.
- Zonefs: Exposing Zoned Block Devices to Userspace — Linux kernel documentation