1use crate::{BlockResult, BlockUtilsError};
2use serde::{Deserialize, Serialize};
3use std::path::Path;
4use std::process::Command;
5
6#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
7#[serde(rename_all = "PascalCase")]
8pub struct NvmeDevice {
9 pub name_space: u64,
10 pub device_path: String,
11 pub index: Option<u64>,
12 pub model_number: String,
13 pub product_name: Option<String>,
14 pub firmware: Option<String>,
15 pub serial_number: String,
16 pub used_bytes: u64,
17 #[serde(rename = "MaximumLBA")]
18 pub maximum_lba: u64,
19 pub physical_size: u64,
20 pub sector_size: u32,
21}
22
23#[derive(Deserialize)]
24#[serde(rename_all = "PascalCase")]
25struct NvmeDeviceContainer {
26 devices: Vec<NvmeDevice>,
27}
28
29pub fn get_error_log(dev: &Path) -> BlockResult<serde_json::Value> {
31 let out = Command::new("nvme")
32 .args(&["error-log", &dev.to_string_lossy(), "-o", "json"])
33 .output()?;
34 if !out.status.success() {
35 return Err(BlockUtilsError::new(
36 String::from_utf8_lossy(&out.stderr).into_owned(),
37 ));
38 }
39 let stdout = String::from_utf8_lossy(&out.stdout);
40 let deserialized: serde_json::Value = serde_json::from_str(&stdout)?;
41 Ok(deserialized)
42}
43
44pub fn get_firmware_log(dev: &Path) -> BlockResult<serde_json::Value> {
46 let out = Command::new("nvme")
47 .args(&["fw-log", &dev.to_string_lossy(), "-o", "json"])
48 .output()?;
49 if !out.status.success() {
50 return Err(BlockUtilsError::new(
51 String::from_utf8_lossy(&out.stderr).into_owned(),
52 ));
53 }
54 let stdout = String::from_utf8_lossy(&out.stdout);
55 let deserialized: serde_json::Value = serde_json::from_str(&stdout)?;
56 Ok(deserialized)
57}
58
59pub fn get_smart_log(dev: &Path) -> BlockResult<serde_json::Value> {
61 let out = Command::new("nvme")
62 .args(&["smart-log", &dev.to_string_lossy(), "-o", "json"])
63 .output()?;
64 if !out.status.success() {
65 return Err(BlockUtilsError::new(
66 String::from_utf8_lossy(&out.stderr).into_owned(),
67 ));
68 }
69 let stdout = String::from_utf8_lossy(&out.stdout);
70 let deserialized: serde_json::Value = serde_json::from_str(&stdout)?;
71 Ok(deserialized)
72}
73
74pub fn get_log(dev: &Path, id: u8, len: u16) -> BlockResult<Vec<u8>> {
76 let out = Command::new("nvme")
77 .args(&[
78 "get-log",
79 &dev.to_string_lossy(),
80 "-i",
81 id.to_string().as_str(),
82 "-l",
83 len.to_string().as_str(),
84 "-b",
85 ])
86 .output()?;
87 if !out.status.success() {
88 return Err(BlockUtilsError::new(
89 String::from_utf8_lossy(&out.stderr).into_owned(),
90 ));
91 }
92 let stdout: Vec<u8> = out.stdout;
93 Ok(stdout)
94}
95
96pub fn format(dev: &Path) -> BlockResult<()> {
98 let out = Command::new("nvme")
99 .args(&["format", &dev.to_string_lossy()])
100 .output()?;
101 if !out.status.success() {
102 return Err(BlockUtilsError::new(
103 String::from_utf8_lossy(&out.stderr).into_owned(),
104 ));
105 }
106 Ok(())
107}
108
109pub fn list_nvme_namespaces(dev: &Path) -> BlockResult<Vec<String>> {
110 let out = Command::new("nvme")
111 .args(&["list-ns", &dev.to_string_lossy(), "-o", "json"])
112 .output()?;
113 if !out.status.success() {
114 return Err(BlockUtilsError::new(
115 String::from_utf8_lossy(&out.stderr).into_owned(),
116 ));
117 }
118 let stdout = String::from_utf8_lossy(&out.stdout);
119 let deserialized: Vec<String> = serde_json::from_str(&stdout)?;
120 Ok(deserialized)
121}
122
123pub fn list_nvme_controllers() -> BlockResult<Vec<String>> {
125 let out = Command::new("nvme-list").args(&["-o", "json"]).output()?;
126 if !out.status.success() {
127 return Err(BlockUtilsError::new(
128 String::from_utf8_lossy(&out.stderr).into_owned(),
129 ));
130 }
131 let stdout = String::from_utf8_lossy(&out.stdout);
132 let deserialized: Vec<String> = serde_json::from_str(&stdout)?;
133 Ok(deserialized)
134}
135
136pub fn list_nvme_devices() -> BlockResult<Vec<NvmeDevice>> {
138 let out = Command::new("nvme")
139 .args(&["list", "-o", "json"])
140 .output()?;
141 if !out.status.success() {
142 return Err(BlockUtilsError::new(
143 String::from_utf8_lossy(&out.stderr).into_owned(),
144 ));
145 }
146 let stdout = String::from_utf8_lossy(&out.stdout);
147 let deserialized: NvmeDeviceContainer = serde_json::from_str(&stdout)?;
148 Ok(deserialized.devices)
149}