Fuchsia Block device drivers are, like other drivers on the system, implemented
as userspace services that are accessible via IPC. Programs using block devices
will have one or more handles to these underlying servers. Similar to filesystem
clients, which may send “read” or “write” requests to servers by encoding these
requests within RPC messages, programs act as clients to block devices using the
fuchsia.storage.block.Block FIDL protocol, which allows clients
to query the block device, open block sessions, and queue FIFO transactions.
fuchsia.storage.block.Block is the protocol served by any
block-like server, whereas
fuchsia.hardware.block.volume.Service is a FIDL service
exposed by block device drivers (USB, AHCI / SATA, NVMe, SDMMC, UFS, Virtio,
Ramdisk, etc) whose volume member implements
fuchsia.storage.block.Block. Block-like servers that are not
drivers may implement fuchsia.storage.block.Block without
exposing the volume service; for example, the GPT component exposes one
Block instance for each partition. Both drivers and other block servers can
use the block_server library to implement
fuchsia.storage.block.Block.
Fast Block I/O
Block device drivers are often responsible for taking large portions of memory, and queueing requests to a particular device to either “read into” or “write from” a portion of memory. Transmitting messages of a limited size from an RPC protocol into an “I/O transaction” would require repeated copying of large buffers to access block devices.
To avoid this performance bottleneck, instead of transmitting “read” or “write”
messages with large buffers over FIDL RPCs, the block protocol uses a fast,
FIFO-based protocol which acts on a shared VMO. Filesystems (or any other
client wishing to interact with a block device) open a session
(fuchsia.storage.block.Session) on a block device, acquire its FIFO handle,
and attach VMOs (AttachVmo) to the session. A client can then send a fast,
lightweight control message on the FIFO, indicating that the block device driver
should act directly on an already-registered VMO. For example, when writing to a
file, rather than passing bytes over IPC primitives directly and copying them to
a new location in the block device’s memory, a filesystem (representing the file
as a VMO) can send a small FIFO message indicating “write N blocks directly from
block offset X of VMO Y to block offset Z on a disk”. When combined with the
“mmap” memory-mapping tools, this provides a “zero-copy” pathway directly from
client programs to disk (or in the other direction) when accessing files.