blk

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2026 License: BSD-3-Clause Imports: 2 Imported by: 0

README

go-virtio/blk

Pure-Go virtio-blk (block device) driver targeting the go-virtio/common transport interfaces. Implements the modern-transport (Virtio 1.0+) init sequence and the request-queue I/O path for the standard PCI-bound virtio-blk device (VID 0x1AF4, DID 0x1042).

Scope

Like go-virtio/net this package owns device bring-up, the single request virtqueue, and the on-the-wire request format (the header + data + status descriptor chain, Virtio 1.1 §5.2.6, built with common.AddChain), exposing a block-level ReadBlocks / WriteBlocks / Flush API. The protocol sector size is always 512 bytes (BlockSize).

VIRTIO_BLK_F_RO is honoured (read-only devices reject writes); no other feature bit is negotiated.

The device backing the driver is the host's concern and is transparent to the guest — it can be a local disk image or a network volume served over NBD (with NBD itself tunnelled through WireGuard or TLS). The driver just sees a block device.

Quick start

import (
    virtioblk "github.com/go-virtio/blk"
)

// transport is any value that implements go-virtio/common.Transport.
vb, err := virtioblk.OpenVirtioBlk(transport)
if err != nil {
    return err
}
fmt.Printf("capacity: %d sectors (%d bytes)\n",
    vb.Capacity, vb.Capacity*virtioblk.BlockSize)

// Read sectors 0..3 (4 × 512 B).
data, err := vb.ReadBlocks(0, 4)

// Write two sectors at LBA 100, then flush.
err = vb.WriteBlocks(100, make([]byte, 2*virtioblk.BlockSize))
err = vb.Flush()

Sibling packages

License

BSD-3-Clause. See LICENSE.

Documentation

Overview

Package blk is a pure-Go virtio-blk (block device) driver. It drives a modern (Virtio 1.0+) PCI virtio-blk device through the transport interfaces defined in github.com/go-virtio/common; the same code drives a UEFI-backed device, a bare-metal device, or a virtio-mmio device depending on which common.Transport implementation the caller supplies.

Scope — like go-virtio/net this package owns device bring-up, the single request virtqueue, and the on-the-wire request format (header + data + status descriptor chain, Virtio 1.1 §5.2.6), exposing a block-level ReadBlocks / WriteBlocks / Flush API. The protocol sector size is always 512 bytes (BlockSize) regardless of any logical block size the device advertises.

  • Modern transport (VIRTIO_F_VERSION_1 mandatory). Legacy devices are rejected by the common init sequence.
  • One request virtqueue; requests are descriptor chains built with common.AddChain.
  • VIRTIO_BLK_F_RO is honoured (read-only devices reject writes). No other feature bit is negotiated (FLUSH works regardless on the devices we target; richer features are out of scope).

References:

  • Virtio 1.1 §5.2 "Block Device" — device-type 2 binding.
  • Virtio 1.1 §5.2.4 "Device configuration layout" — le64 capacity.
  • Virtio 1.1 §5.2.6 "Device Operation" — struct virtio_blk_req.
  • Virtio 1.1 §3.1.1 "Device Initialization".

Index

Constants

View Source
const (
	BlkTypeIn    uint32 = 0 // read (device writes data)
	BlkTypeOut   uint32 = 1 // write (device reads data)
	BlkTypeFlush uint32 = 4
)

Request types (Virtio 1.1 §5.2.6 — virtio_blk_req.type).

View Source
const (
	BlkStatusOK     uint8 = 0
	BlkStatusIOErr  uint8 = 1
	BlkStatusUnsupp uint8 = 2
)

Status byte values (Virtio 1.1 §5.2.6 — the device-writable trailer).

View Source
const AcceptedFeatures uint64 = common.FeatureVersion1

AcceptedFeatures is the feature mask the driver negotiates ON — only the non-negotiable VIRTIO_F_VERSION_1. (F_RO is inspected from the device's offered set but is not a driver-acked bit.)

View Source
const BlkReqHeaderSize = 16

BlkReqHeaderSize is the on-the-wire size of struct virtio_blk_req's header (Virtio 1.1 §5.2.6.1): le32 type, le32 reserved, le64 sector.

View Source
const BlockSize = 512

BlockSize is the virtio-blk protocol sector size — always 512 bytes (Virtio 1.1 §5.2.6); the device's `sector` fields count 512-byte units.

View Source
const DeviceType uint16 = 2

DeviceType is the virtio device-type encoding for virtio-blk (Virtio 1.1 §5.2.1). Retained from the package's placeholder era for callers enumerating PCI devices that want a stable name.

View Source
const RequestQueueIdx uint16 = 0

RequestQueueIdx is the index of the single virtio-blk request queue.

View Source
const RequestQueueSize uint16 = 16

RequestQueueSize is the desired ring size (clamped + rounded during setup). A request consumes 2–3 descriptors, so this bounds the number of in-flight requests; the driver issues them one at a time.

View Source
const TxPollIterations = 200000

TxPollIterations is the default busy-poll budget for one request.

Variables

View Source
var (
	ErrNotModernDevice   = commonBlkError("go-virtio/blk: device doesn't offer VIRTIO_F_VERSION_1 (legacy-only)")
	ErrFeaturesNotOK     = commonBlkError("go-virtio/blk: FEATURES_OK status bit didn't stick after DriverFeature write")
	ErrInitWrongDeviceID = commonBlkError("go-virtio/blk: PCI device ID is not 0x1042 (modern block device)")
	ErrQueueNotAvailable = commonBlkError("go-virtio/blk: device reports QueueSize=0 for the request queue")
	ErrRequestTimeout    = commonBlkError("go-virtio/blk: request poll timeout (device did not complete the request)")
	ErrZeroCount         = commonBlkError("go-virtio/blk: ReadBlocks count must be positive")
	ErrUnalignedLength   = commonBlkError("go-virtio/blk: write length must be a positive multiple of BlockSize (512)")
	ErrReadOnly          = commonBlkError("go-virtio/blk: device is read-only (VIRTIO_BLK_F_RO)")
	ErrIO                = commonBlkError("go-virtio/blk: device reported VIRTIO_BLK_S_IOERR")
	ErrUnsupported       = commonBlkError("go-virtio/blk: device reported VIRTIO_BLK_S_UNSUPP")
)

Sentinel errors for the virtio-blk path.

Functions

func AcceptFeatures added in v0.2.0

func AcceptFeatures(deviceFeatures uint64) (uint64, error)

AcceptFeatures returns the negotiated mask (requires VERSION_1).

Types

type VirtioBlk added in v0.2.0

type VirtioBlk struct {
	// Cfg is the modern-transport handle.
	Cfg *common.ModernConfig

	// Capacity is the device size in 512-byte sectors (Virtio 1.1
	// §5.2.4), read from DeviceCfg at OpenVirtioBlk.
	Capacity uint64

	// ReadOnly reflects VIRTIO_BLK_F_RO in the device's offered features.
	ReadOnly bool

	// NegotiatedFeatures records the driver-feature handshake result.
	NegotiatedFeatures uint64
	// contains filtered or unexported fields
}

VirtioBlk wraps one initialised virtio-blk device.

func OpenVirtioBlk added in v0.2.0

func OpenVirtioBlk(t common.Transport) (*VirtioBlk, error)

OpenVirtioBlk drives the full bring-up of one virtio-blk device:

  1. Verify the PCI device ID is 0x1042 (modern block).
  2. InitModernConfig walks PCI caps + populates the BAR locators.
  3. Reset → ACK → DRIVER status progression.
  4. Read DeviceFeature, record RO, mask to VERSION_1, write DriverFeature.
  5. Set FEATURES_OK, verify it stuck.
  6. Allocate + publish the request queue (queue 0).
  7. DRIVER_OK status.
  8. Read capacity (le64 sectors) from DeviceCfg.

func (*VirtioBlk) Flush added in v0.2.0

func (b *VirtioBlk) Flush() error

Flush issues a VIRTIO_BLK_T_FLUSH request, asking the device to commit volatile write caches to stable storage.

func (*VirtioBlk) ReadBlocks added in v0.2.0

func (b *VirtioBlk) ReadBlocks(sector uint64, count int) ([]byte, error)

ReadBlocks reads `count` 512-byte sectors starting at `sector` and returns the data. count must be positive.

func (*VirtioBlk) RequestQueue added in v0.2.0

func (b *VirtioBlk) RequestQueue() *common.Virtqueue

RequestQueue exposes the request virtqueue handle for diagnostics.

func (*VirtioBlk) WriteBlocks added in v0.2.0

func (b *VirtioBlk) WriteBlocks(sector uint64, data []byte) error

WriteBlocks writes `data` (a whole number of 512-byte sectors) starting at `sector`. Returns ErrReadOnly if the device is read-only, or ErrUnalignedLength if len(data) is not a positive multiple of BlockSize.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL