Virtio Disk Driver

---
config:
  layout: dagre
---
flowchart LR
 subgraph C["caller side"]
    direction TB
        FS["filesystem / log layer<br><br>readi / writei<br>log_write / install_trans"]
        BCACHE["buffer cache<br><br>bread<br>bwrite"]
        BUF["struct buf<br><br>dev<br>blockno<br>valid<br>disk<br>data[BSIZE]"]
  end
 subgraph VDI["virtio disk interface"]
    direction TB
        VINIT["virtio_disk_init()<br><br>verify device<br>negotiate features<br>initialize queue 0"]
        VRW["virtio_disk_rw(b, write)<br><br>build disk request<br>submit to virtqueue<br>sleep until done"]
        VINTR["virtio_disk_intr()<br><br>ack interrupt<br>process used ring<br>wake completed buffers"]
  end
 subgraph VDS["virtio disk state"]
    direction TB
        DISK["struct disk<br><br>vdisk_lock<br>free[]<br>used_idx<br>info[]<br>ops[]"]
        VQ["virtqueue<br><br>desc[]<br>avail ring<br>used ring"]
  end
 subgraph HW["virtio disk hardware source"]
    direction TB
        MMIO["virtio MMIO registers<br><br>STATUS<br>QUEUE_NOTIFY<br>INTERRUPT_STATUS<br>INTERRUPT_ACK"]
        DEVICE["qemu virtio-blk device<br><br>reads / writes fs.img blocks"]
        IRQ["VIRTIO0_IRQ<br><br>external interrupt"]
  end
 subgraph I["interrupt delivery"]
    direction TB
        PLIC_PATH["PLIC + devintr()<br><br>claim virtio IRQ<br>call virtio_disk_intr<br>complete IRQ"]
  end
    FS -- needs disk block --> BCACHE
    BCACHE -- uses locked buffer --> BUF
    BCACHE -- cache miss or writeback --> VRW
    VINIT -- sets up --> DISK
    VINIT -- allocates and registers --> VQ
    VINIT -- configures --> MMIO
    VRW -- uses buffer data --> BUF
    VRW -- allocates 3 descriptors<br>header + data + status --> VQ
    VRW -- "records in-flight request" --> DISK
    VRW -- notifies queue 0 --> MMIO
    MMIO -- device sees available request --> DEVICE
    DEVICE -- DMA reads/writes buffer block --> VQ
    DEVICE -- completion interrupt --> IRQ
    IRQ -- external interrupt --> PLIC_PATH
    PLIC_PATH -- calls --> VINTR
    VINTR -- acknowledges interrupt --> MMIO
    VINTR -- reads completed entries --> VQ
    VINTR -- "clears b->disk and wakeup(b)" --> BUF

     FS:::process
     BCACHE:::iface
     BUF:::file
     VINIT:::iface
     VRW:::iface
     VINTR:::iface
     DISK:::source
     VQ:::source
     MMIO:::source
     DEVICE:::source
     IRQ:::source
     PLIC_PATH:::backend
    classDef process fill:#F3EFE2,stroke:#111,stroke-width:2px,color:#111
    classDef file fill:#FFFFFF,stroke:#111,stroke-width:3px,color:#111
    classDef source fill:#E9F1FF,stroke:#111,stroke-width:2px,color:#111
    classDef iface fill:#EDE7D4,stroke:#111,stroke-width:2px,color:#111
    classDef backend fill:#F8F8F8,stroke:#111,stroke-width:2px,color:#111