Disk
A Disk wraps one virtio-blk disk attached to a VM. It exposes block-level operations and a fault-injection surface useful for exercising I/O error paths in the guest.
Constructing #
| Source | Returns |
|---|---|
vm:attach_disk({id="vda", size=…, image="…"}) | New disk attached to vm. |
vm:disk("id") | Lookup of an already-attached disk. Errors if absent. |
vm:attach_disk opts:
| Field | Type | Default | Description |
|---|---|---|---|
id | string | "attached-<vm_name>" | Disk identifier within the VM. |
size | int (bytes) | 4 GiB | Modelled disk size. Used for :size() when no image is attached. |
image | string (path) | none | Backing file. Sector ops require an image. |
Disks are 512-byte sectors throughout. The read_sectors and write_sectors ops express offsets and counts in sectors.
Methods #
disk:size() #
Returns the disk's size in bytes. When a backing image is attached, returns the live stat() size of the image file (so a test that resized the underlying file with truncate / fallocate reads honest output). Without an image, returns the modelled size from attach_disk.
disk:read_sectors(offset, n) #
Read n sectors starting at sector offset. Returns the bytes as a Lua string. Errors if:
- The disk is detached (
disk:read_sectors: disk is detached). - No backing image (
disk:read_sectors: no backing image — disk:with_image required). - An
eio_readfault is active (disk:read_sectors: EIO (fault_inject)). - The host-side
readfails (passes the underlying error through).
Honours active faults:
eio_read— short-circuits to EIO before any I/O.slow— sleeps 50 ms per call. After the sleep, re-checks foreio_readso a concurrent fault injection during the sleep still takes effect. After the actual I/O, checks one more time for the same reason.
disk:write_sectors(offset, data) #
Write data (a Lua string) starting at sector offset. The data does not have to be a multiple of 512 bytes; it is written verbatim from the offset. Returns nothing.
Errors and fault handling mirror read_sectors:
- Detached → error.
- No backing image → error.
eio_writeactive before the I/O → EIO.slow→ 50 ms sleep, witheio_writere-checks after the sleep and after the I/O.
disk:fault_inject(mode) #
Activate a fault. Valid modes: "eio_read", "eio_write", "slow". Unknown modes error with the valid list (disk:fault_inject: unknown mode \X` (valid: eio_read, eio_write, slow)`).
Multiple modes can be active simultaneously. When slow and the matching eio_* are both active at call time, the EIO check runs first — the call errors immediately, without the 50 ms delay. (The post-sleep re-checks only matter for an EIO fault set after the call started.)
disk:clear_faults() #
Clear every active fault. Subsequent reads / writes succeed normally.
disk:active_faults() #
Returns a Lua array of the currently-active fault mode names. Useful for tests that need to assert the harness state.
disk:detach() #
Mark the disk as detached and issue a best-effort QMP device_del against the parent VM. Subsequent read_sectors / write_sectors error. The QMP call is best-effort: a disk that was never QMP-added (host-bookkeeping-only attach) silently surfaces "Device not found" but the local detached flag is still set.
disk:is_detached() / disk:id() #
Accessors. :id() returns the disk identifier as given to attach_disk.
Example: full fault-injection pattern #
test
See also #
- VM — disks come from
vm:attach_disk/vm:disk. - Disks and fault injection — patterns for exercising I/O error paths.