(
id: String,
disk_image: Box<dyn AsyncFullDiskFile>,
disk_path: PathBuf,
read_only: bool,
access_platform_enabled: bool,
num_queues: usize,
que
| 743 | /// Create a new virtio block device that operates on the given file. |
| 744 | #[allow(clippy::too_many_arguments)] |
| 745 | pub fn new( |
| 746 | id: String, |
| 747 | disk_image: Box<dyn AsyncFullDiskFile>, |
| 748 | disk_path: PathBuf, |
| 749 | read_only: bool, |
| 750 | access_platform_enabled: bool, |
| 751 | num_queues: usize, |
| 752 | queue_size: u16, |
| 753 | serial: Option<String>, |
| 754 | seccomp_action: SeccompAction, |
| 755 | rate_limiter: Option<Arc<RateLimiterGroup>>, |
| 756 | exit_evt: EventFd, |
| 757 | state: Option<BlockState>, |
| 758 | queue_affinity: BTreeMap<u16, Vec<usize>>, |
| 759 | sparse: bool, |
| 760 | disable_sector0_writes: bool, |
| 761 | lock_granularity: LockGranularityChoice, |
| 762 | ) -> io::Result<Self> { |
| 763 | let (disk_nsectors, avail_features, acked_features, config, paused) = |
| 764 | if let Some(state) = state { |
| 765 | info!("Restoring virtio-block {id}"); |
| 766 | ( |
| 767 | state.disk_nsectors, |
| 768 | state.avail_features, |
| 769 | state.acked_features, |
| 770 | state.config, |
| 771 | true, |
| 772 | ) |
| 773 | } else { |
| 774 | let disk_size = disk_image |
| 775 | .logical_size() |
| 776 | .map_err(|e| io::Error::other(format!("Failed getting disk size: {e}")))?; |
| 777 | if disk_size % SECTOR_SIZE != 0 { |
| 778 | warn!( |
| 779 | "Disk size {disk_size} is not a multiple of sector size {SECTOR_SIZE}; \ |
| 780 | the remainder will not be visible to the guest." |
| 781 | ); |
| 782 | } |
| 783 | |
| 784 | let mut avail_features = (1u64 << VIRTIO_F_VERSION_1) |
| 785 | | (1u64 << VIRTIO_BLK_F_FLUSH) |
| 786 | | (1u64 << VIRTIO_BLK_F_CONFIG_WCE) |
| 787 | | (1u64 << VIRTIO_BLK_F_BLK_SIZE) |
| 788 | | (1u64 << VIRTIO_BLK_F_TOPOLOGY) |
| 789 | | (1u64 << VIRTIO_BLK_F_SEG_MAX) |
| 790 | | (1u64 << VIRTIO_RING_F_EVENT_IDX) |
| 791 | | (1u64 << VIRTIO_RING_F_INDIRECT_DESC); |
| 792 | |
| 793 | // When backend supports sparse operations: |
| 794 | // - Always advertise WRITE_ZEROES (safe for all drivers) |
| 795 | // - Advertise DISCARD only when sparse=true, since DISCARD |
| 796 | // deallocates space via punch_hole and should require |
| 797 | // explicit user opt in. |
| 798 | let mut discard_supported = false; |
| 799 | if disk_image.supports_sparse_operations() { |
| 800 | avail_features |= 1u64 << VIRTIO_BLK_F_WRITE_ZEROES; |
| 801 | if sparse { |
| 802 | avail_features |= 1u64 << VIRTIO_BLK_F_DISCARD; |
nothing calls this directly
no test coverage detected