Skip to content

fix: false hdd detection on virtual devices#352

Draft
KSXGitHub wants to merge 81 commits intoKSXGitHub:masterfrom
khai-slop-labs:claude/fix-hdd-detection-OQvIf
Draft

fix: false hdd detection on virtual devices#352
KSXGitHub wants to merge 81 commits intoKSXGitHub:masterfrom
khai-slop-labs:claude/fix-hdd-detection-OQvIf

Conversation

@KSXGitHub
Copy link
Owner

@KSXGitHub KSXGitHub commented Mar 11, 2026

Summary

Fixes virtual block devices (VirtIO, Xen, Hyper-V, VMware) on Linux being misclassified as HDDs. The kernel's rotational sysfs flag defaults to 1 for virtual devices, causing sysinfo to report them as HDDs. This PR checks the block device's driver via /sys/block/<dev>/device/driver and reclassifies known virtual drivers as DiskKind::Unknown(-1).

Key Changes

  • Replaced Api trait with DiskApi (&self methods, impl'd directly on disk types) + FsApi (static filesystem operations) for fine-grained test mocking
  • Added reclassify_virtual_hdd() — checks sysfs driver and reclassifies virtual devices (Linux-only; no-op on other platforms)
  • Added extract_block_device_name() — resolves /dev/mapper/, /dev/root symlinks and parses device paths (sd*, vd*, xvd*, nvme*, mmcblk*)
  • Added is_virtual_block_device() — matches drivers: virtio_blk, xen_blkfront, xen-blkfront, vbd, vmw_pvscsi, hv_storvsc
  • Changed path_is_in_hdd to filter by mount point first, then check disk kind
  • Known limitation: LVM/device-mapper (/dev/dm-*) volumes are not traced to backing devices

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K

The sysinfo crate reads /sys/block/*/queue/rotational to determine disk
type, but virtual block devices (VirtIO, Xen, VMware PVSCSI, Hyper-V)
default to rotational=1 because the kernel doesn't know the backing
storage type. This caused pdu to falsely detect virtual disks as HDDs
and unnecessarily limit threads to 1.

The fix adds a secondary check on Linux: when sysinfo reports HDD, we
read the block device's driver via /sys/block/<dev>/device/driver and
reclassify known virtual drivers (virtio_blk, xen_blkfront, vmw_pvscsi,
hyperv_storvsc) as Unknown instead of HDD.

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K
Apply rustfmt formatting and replace map_or with is_some_and per clippy.

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts HDD detection on Linux to avoid misclassifying virtual block devices as HDDs when sysinfo reports DiskKind::HDD due to the kernel’s rotational=1 default on some virtual devices.

Changes:

  • Intercept DiskKind::HDD on Linux and reclassify known virtual block-device drivers to DiskKind::Unknown(-1).
  • Add Linux-only helpers to extract a base block device name and check the sysfs driver symlink.
  • Add Linux-specific tests for device-name extraction and virtual-driver detection.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

File Description
src/app/hdd.rs Adds Linux-only correction path for HDD detection via /sys/block/<dev>/device/driver, plus device-name extraction.
src/app/hdd/test.rs Adds Linux-only tests around extraction and virtual device detection (currently environment-dependent).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

claude and others added 22 commits March 11, 2026 12:12
- Fix Hyper-V driver name: use 'hv_storvsc' (actual kernel name) instead
  of 'hyperv_storvsc'
- Split extract_block_device_name into parse_block_device_name (pure
  parsing, no I/O) and validate_block_device (sysfs check), making the
  parsing logic independently testable
- Update doc comments to document /dev/root handling
- Make tests hermetic: test_parse_block_device_name asserts deterministically
  on all cases without depending on sysfs availability
- Improve test_extract_and_check_real_disks to validate all disk types,
  not just VirtIO

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K
On macOS and FreeBSD, sysinfo reports DiskKind::Unknown because there is
no reliable OS API for rotational vs solid-state detection. The HDD code
path is never reached on those platforms today. Added a doc comment
explaining this and noting the fragility if sysinfo improves detection.

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K
The Api trait's purpose is to enable dependency injection by delegating
to sysinfo::Disk methods. get_disk_kind should only call disk.kind(),
not apply platform-specific corrections.

- RealApi::get_disk_kind now purely delegates to disk.kind()
- Added get_disk_name to Api trait (delegates to disk.name())
- correct_hdd_detection takes (DiskKind, &str) instead of &Disk
- Correction is applied in new is_in_hdd helper called from path_is_in_hdd
- Updated MockedApi to implement get_disk_name

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K

This comment was marked as resolved.

This comment was marked as resolved.

KSXGitHub and others added 2 commits March 16, 2026 03:46
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
The value passed (e.g. `/dev/vda1`) is a device path forwarded to
`reclassify_virtual_hdd` as `disk_name`, not a filesystem mount point.
Rename the macro parameter and doc string to match.

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K

This comment was marked as resolved.

This comment was marked as resolved.

claude added 2 commits March 15, 2026 21:24
Add the hyphenated `virtio-blk` driver name alongside the existing
`virtio_blk` for consistency with the Xen dual-name treatment. Add a
comment clarifying why the recursive `extract_block_device_name` call
is safe (canonicalize resolves all symlinks).

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K
Replace all occurrences of `DiskKind::Unknown(-1)` with a named
constant to make the intent explicit and avoid coupling to a specific
numeric value across implementation and tests.

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K
…ariable

`is_in_hdd` checks whether a disk IS an HDD, not whether something is
IN an HDD — rename to `is_hdd`. Also rename the leftover `$mount`
macro capture variable to `$disk_name` to match its parameter name.

https://claude.ai/code/session_01MHKaZm6DcA9kjBPnW3KN5K

This comment was marked as resolved.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.


You can also share your feedback on Copilot code review. Take the survey.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +1 to +36
use super::{extract_block_device_name, is_virtual_block_device, RealFs};

/// On hosts with a `/sys/block/vda` device, exercises the detection
/// pipeline without panicking. Silently skips if `vda` does not exist.
#[test]
fn real_sysfs_vda_does_not_panic() {
if std::path::Path::new("/sys/block/vda").exists() {
let _ = is_virtual_block_device::<RealFs>("vda");
}
}

/// A non-existent device name must return `false` without panicking.
#[test]
fn nonexistent_device_is_not_virtual() {
assert!(
!is_virtual_block_device::<RealFs>("nonexistent_device_xyz"),
"non-existent device should not be detected as virtual"
);
}

/// Runs the full detection pipeline on every mounted disk.
///
/// Does **not** assert any specific virtual/non-virtual classification
/// because the result depends on the host hardware. Only verifies that
/// the pipeline completes without panicking.
#[test]
fn full_pipeline_does_not_panic() {
use sysinfo::Disks;
let disks = Disks::new_with_refreshed_list();
for disk in disks.list() {
let name = disk.name().to_str().unwrap_or_default();
if let Some(block_dev) = extract_block_device_name::<RealFs>(name) {
let _ = is_virtual_block_device::<RealFs>(&block_dev);
}
}
}
Comment on lines +31 to +32
let name = disk.name().to_str().unwrap_or_default();
if let Some(block_dev) = extract_block_device_name::<RealFs>(name) {
Comment on lines +239 to +240
| "vmw_pvscsi"
| "hv_storvsc"
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.


You can also share your feedback on Copilot code review. Take the survey.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants