#[cfg(all(target_os = "linux", feature = "uring-cmd-nvme"))]
use std::fs;
#[cfg(all(target_os = "linux", feature = "uring-cmd-nvme"))]
use std::io::{ErrorKind, Read as _};
#[cfg(all(target_os = "linux", feature = "uring-cmd-nvme"))]
const MAX_NVIDIA_FS_STATS_BYTES: u64 = 1024 * 1024;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum GpuDirectCapability {
Available {
stats: String,
},
Unavailable {
reason: &'static str,
},
FeatureDisabled,
}
impl GpuDirectCapability {
#[must_use]
pub fn probe() -> Self {
#[cfg(not(all(target_os = "linux", feature = "uring-cmd-nvme")))]
{
GpuDirectCapability::FeatureDisabled
}
#[cfg(all(target_os = "linux", feature = "uring-cmd-nvme"))]
match read_nvidia_fs_stats() {
Ok(stats) if !stats.trim().is_empty() => {
GpuDirectCapability::Available { stats }
}
Ok(_) => GpuDirectCapability::Unavailable {
reason: "nvidia-fs stats file is empty; driver reports no GPUDirect sessions",
},
Err(err) if err.kind() == ErrorKind::NotFound => GpuDirectCapability::Unavailable {
reason: "/proc/driver/nvidia-fs/stats not found; nvidia-fs is not installed",
},
Err(err) if err.kind() == ErrorKind::PermissionDenied => GpuDirectCapability::Unavailable {
reason: "/proc/driver/nvidia-fs/stats refused permission; run with adequate privileges",
},
Err(_) => GpuDirectCapability::Unavailable {
reason: "/proc/driver/nvidia-fs/stats read failed for an unexpected reason",
},
}
}
#[must_use]
pub fn is_available(&self) -> bool {
matches!(self, GpuDirectCapability::Available { .. })
}
}
#[cfg(all(target_os = "linux", feature = "uring-cmd-nvme"))]
fn read_nvidia_fs_stats() -> std::io::Result<String> {
let mut file = fs::File::open("/proc/driver/nvidia-fs/stats")?;
let mut stats = String::new();
file.by_ref()
.take(MAX_NVIDIA_FS_STATS_BYTES + 1)
.read_to_string(&mut stats)?;
let stats_len = u64::try_from(stats.len()).map_err(|error| {
std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("nvidia-fs stats length cannot fit u64: {error}"),
)
})?;
if stats_len > MAX_NVIDIA_FS_STATS_BYTES {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"nvidia-fs stats exceeded bounded read limit",
));
}
Ok(stats)
}
pub const NVME_CMD_READ: u8 = 0x02;
#[must_use]
pub fn encode_nvme_read_sqe(
namespace_id: u32,
starting_lba: u64,
blocks: u32,
dest_bar1_ptr: u64,
) -> [u8; 64] {
assert!(
blocks > 0,
"NVMe read SQE cannot encode zero blocks; validate read length before submitting GPU-direct ingest"
);
let mut buf = [0u8; 64];
buf[0] = NVME_CMD_READ;
buf[4..8].copy_from_slice(&namespace_id.to_le_bytes());
buf[32..40].copy_from_slice(&dest_bar1_ptr.to_le_bytes());
buf[40..48].copy_from_slice(&starting_lba.to_le_bytes());
let zero_based = blocks - 1;
buf[48..52].copy_from_slice(&zero_based.to_le_bytes());
buf
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn probe_returns_a_structured_variant() {
match GpuDirectCapability::probe() {
GpuDirectCapability::Available { .. } => {}
GpuDirectCapability::Unavailable { .. } => {}
GpuDirectCapability::FeatureDisabled => {}
}
}
#[test]
fn encode_nvme_read_sqe_layout_matches_spec() {
let sqe = encode_nvme_read_sqe(
1,
0x1122_3344_5566_7788,
8,
0xAABB_CCDD_EEFF_0011,
);
assert_eq!(sqe[0], NVME_CMD_READ);
assert_eq!(sqe[4..8], 1u32.to_le_bytes());
assert_eq!(sqe[32..40], 0xAABB_CCDD_EEFF_0011u64.to_le_bytes());
assert_eq!(sqe[40..48], 0x1122_3344_5566_7788u64.to_le_bytes());
assert_eq!(sqe[48..52], 7u32.to_le_bytes());
assert_eq!(&sqe[8..32], &[0u8; 24]);
assert_eq!(&sqe[52..64], &[0u8; 12]);
}
#[test]
fn encode_nvme_single_block_yields_zero_in_nblocks_field() {
let sqe = encode_nvme_read_sqe(1, 0, 1, 0);
assert_eq!(sqe[48..52], 0u32.to_le_bytes());
}
#[test]
fn is_available_reflects_variant() {
let available = GpuDirectCapability::Available {
stats: "session_count=1".into(),
};
assert!(available.is_available());
let unavail = GpuDirectCapability::Unavailable {
reason: "test reason",
};
assert!(!unavail.is_available());
assert!(!GpuDirectCapability::FeatureDisabled.is_available());
}
}