Virtio文档阅读笔记(三)具体设备
以下设备的顺序与文档顺序不太一样, 或者不全, 日后会补, 遗留的特征等不会写上来
块设备
什么是块设备
在文档中的定义如下: Virtio块设备是一个简单的虚拟块设备, 比如磁盘等, 读取和写入请求被放入在了队列中, 并由设备处理(可能不是顺序处理), 块设备的Device ID为2
块设备的特征bits
bit | 特证名 | 解释 |
---|---|---|
1 | VIRTIO_BLK_F_SIZE_MAX | 最大的任何segment的大小放在了size_max |
2 | VIRTIO_BLK_F_SEG_MAX | 一个request的最大数量segment放在了seg_max |
4 | VIRTIO_BLK_F_GEOMETRY | Disk-style geometry放在了geometry |
5 | VIRTIO_BLK_F_RO | 设备是只读 |
6 | VIRTIO_BLK_F_BLK_SIZE | 磁盘的块大小放在了blk_size |
9 | VIRTIO_BLK_F_FLUSH | 支持缓存刷新命令 |
10 | VIRTIO_BLK_F_TOPOLOGY | 设备利用最佳I/O对齐(optimal I/O alignment)导出消息 |
11 | VIRTIO_BLK_F_CONFIG_WCE | 设备的缓存可以在writeback和writethrough模式之间循环切换 |
13 | VIRTIO_BLK_F_DISCARD | 设备可以支持discard(丢弃)命令, 最多可以discard的sector数量放在了max_discard_sectors 以及最多可以discard的segment数量放在了max_discard_seg |
14 | VIRTIO_BLK_F_WRITE_ZEROES | 设备可以支持全写0命令, 最多可以全写0的sector数量放在了max_discard_sectors 以及最多可以全写0的segment数量放在了max_discard_seg |
设备配置空间
这里直接放个文档中的截图, le64代表小端64bit, le32代表小端32bit, le16代表小端16bit, u8代表8bit
其中capacity
代表一个设备能支持的最大容量, 单位为512byte的扇区, 这一字段总是存在的, 其他的需要特征是否启用, 配置空间中的max_discard_secotrs
, discard_sector_alignment
以及max_write_zeroes_sectors
的单位均为512-byte.
设备初始化
- 设备的大小可以从
capacity
中获取到 - 如果有VIRTIO_BLK_F_BLK_SIZE特征, 则
blk_size
可以用来决定最佳的扇区大小,这不会影响协议中其他的单位(均为512bytes). - 如果有VIRTIO_BLK_F_RO特征, 则所有的写操作都会失效
- 如果有VIRTIO_BLK_F_TOPOLOGY特征, 则驱动可以使用
topology
结构体可以用来决定物理块大小和最佳的I/O长度, 同样不会影响协议中其他的单位 - 如果有VIRTIO_BLK_F_CONFIG_WCE特征, 则可以通过读取或者写入writeback来获取/修改缓存模式, 0代表writethrough模式, 1代表writeback模式
- 如果有VIRTIO_BLK_F_DISCARD特征, 则驱动可以使用
max_discard_sectors
和max_discard_seg
来获得最大可以discard的扇区以及segments, 当基于对齐拆分请求时, 操作系统可以使用discard_sector_alignment
- 如果有VIRTIO_BLK_F_WRITE_ZEROES特征, 则驱动可以使用
max_write_zeroes_sectors
和max_write_zeroes_seg
来获得最大可以写入0的扇区以及segments
驱动注意事项
- 驱动不能请求VIRTIO_BLK_F_FLUSH特征如果驱动不能发送VIRTIO_BLK_F_FLUSH命令
- 如果VIRTIO_BLK_F_CONFIG_WCE以及VIRTIO_BLK_F_FLUSH都没有仲裁, 那么驱动应该假设使用了缓存使用了writethrough模式, 如果前者没有仲裁, 后者由, 则驱动应该假设缓存使用了writeback模式
- 在FEATURES_OK之前, 驱动不能读取
writeback
字段
设备操作
驱动使用virtqueue来请求服务, 每个请求大致结构如下:
其中的type只能取下面其中之一的值:
值 | 名 | 解释 |
---|---|---|
0 | VIRTIO_BLK_T_IN | 请求读取块设备中的数据 |
1 | VIRTIO_BLK_T_OUT | 请求写入数据到块设备中 |
4 | VIRTIO_BLK_T_FLUSH | 刷新指令(缓存?可能是) |
11 | VIRTIO_BLK_T_DISCARD | discard指令 |
13 | VIRTIO_BLK_T_WRITE_ZEROS | write zeroes指令 |
sector
字段代表从哪个位置读取或者写入数据, 单位为512 bytes, 如果不是IN或者OUT则要设为0, discard或者write zeroes指令需要更多的字段, 这些字段被放在了data中, 字段的结构如下:
其中sector
与IN或者OUT代表的意义一样, num_sectors
代表操作多少个扇区, unmap
只用在write zeros命令, 允许设备discard一个特定的区域, 前提是后续读取返回0
最终读取的状态由设备写入, 他们的值以及代表的意义为:
- VIRTIO_BLK_S_OK 0: 成功
- VIRTIO_BLK_S_IOERR 1: 设备或者驱动出错
- VIRTIO_BLK_S_UNSUPP: 设备不支持的请求
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 sdww0的博客!
评论