Skip to content

Commit 2a09867

Browse files
authored
Merge pull request #2 from oxidecomputer/mike/namespace-info
Add support for namespace info
2 parents aeeb8dd + d06590f commit 2a09867

File tree

5 files changed

+109
-37
lines changed

5 files changed

+109
-37
lines changed

libnvme-sys/header-check/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ fn main() {
4343
"nvme_ns_iter" => true,
4444
"nvme_ns_disc" => true,
4545
"nvme_ns" => true,
46+
"nvme_ns_info" => true,
4647
"nvme_nvm_lba_fmt" => true,
4748
"nvme_format_req" => true,
4849
"di_node" => true,
@@ -59,6 +60,7 @@ fn main() {
5960
"nvme_ns_iter_t" => true,
6061
"nvme_ns_disc_t" => true,
6162
"nvme_ns_t" => true,
63+
"nvme_ns_info_t" => true,
6264
"nvme_nvm_lba_fmt_t" => true,
6365
"nvme_format_req_t" => true,
6466
"di_node_t" => true,

libnvme-sys/src/nvme.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ opaque_type!(nvme_ctrl_info, nvme_ctrl_info_t);
141141
opaque_type!(nvme_ns_iter, nvme_ns_iter_t);
142142
opaque_type!(nvme_ns_disc, nvme_ns_disc_t);
143143
opaque_type!(nvme_ns, nvme_ns_t);
144+
opaque_type!(nvme_ns_info, nvme_ns_info_t);
144145
opaque_type!(nvme_nvm_lba_fmt, nvme_nvm_lba_fmt_t);
145146
opaque_type!(nvme_format_req, nvme_format_req_t);
146147

@@ -232,6 +233,20 @@ extern "C" {
232233
) -> bool;
233234
pub fn nvme_ns_fini(arg1: *mut nvme_ns_t);
234235

236+
// NVMe Namespace information.
237+
pub fn nvme_ns_info_snap(
238+
arg1: *mut nvme_ns_t,
239+
arg2: *mut *mut nvme_ns_info_t,
240+
) -> bool;
241+
pub fn nvme_ns_info_free(arg1: *mut nvme_ns_info_t);
242+
pub fn nvme_ns_info_err(arg1: *mut nvme_ns_info_t) -> nvme_info_err_t;
243+
pub fn nvme_ns_info_errmsg(arg1: *mut nvme_ns_info_t) -> *const c_char;
244+
pub fn nvme_ns_info_syserr(arg1: *mut nvme_ns_info_t) -> c_int;
245+
pub fn nvme_ns_info_curformat(
246+
arg1: *mut nvme_ns_info_t,
247+
arg2: *mut *const nvme_nvm_lba_fmt,
248+
) -> bool;
249+
235250
// Controller Locking.
236251
pub fn nvme_ctrl_lock(
237252
arg1: *mut nvme_ctrl_t,

libnvme/src/controller_info.rs

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
};
1616

1717
#[derive(Debug, Error)]
18-
pub enum ControllerInfoError {
18+
pub enum NvmeInfoError {
1919
#[error(transparent)]
2020
Ok(InternalError),
2121
#[error(transparent)]
@@ -38,31 +38,22 @@ pub enum ControllerInfoError {
3838
NsNoBlkdev(InternalError),
3939
}
4040

41-
impl ControllerInfoError {
42-
fn from_raw_with_internal_error(raw: u32, internal: InternalError) -> Self {
41+
impl NvmeInfoError {
42+
pub(crate) fn from_raw_with_internal_error(
43+
raw: u32,
44+
internal: InternalError,
45+
) -> Self {
4346
match raw {
44-
NVME_INFO_ERR_OK => ControllerInfoError::Ok(internal),
45-
NVME_INFO_ERR_TRANSPORT => ControllerInfoError::Transport(internal),
46-
NVME_INFO_ERR_VERSION => ControllerInfoError::Version(internal),
47-
NVME_INFO_ERR_MISSING_CAP => {
48-
ControllerInfoError::MissingCap(internal)
49-
}
50-
NVME_INFO_ERR_BAD_LBA_FMT => {
51-
ControllerInfoError::BadLbaFmt(internal)
52-
}
53-
NVME_INFO_ERR_PERSIST_NVL => {
54-
ControllerInfoError::PersistNvl(internal)
55-
}
56-
NVME_INFO_ERR_BAD_FMT => ControllerInfoError::BadFmt(internal),
57-
NVME_INFO_ERR_BAD_FMT_DATA => {
58-
ControllerInfoError::BadFmtData(internal)
59-
}
60-
NVME_INFO_ERR_NS_INACTIVE => {
61-
ControllerInfoError::NsInactive(internal)
62-
}
63-
NVME_INFO_ERR_NS_NO_BLKDEV => {
64-
ControllerInfoError::NsNoBlkdev(internal)
65-
}
47+
NVME_INFO_ERR_OK => NvmeInfoError::Ok(internal),
48+
NVME_INFO_ERR_TRANSPORT => NvmeInfoError::Transport(internal),
49+
NVME_INFO_ERR_VERSION => NvmeInfoError::Version(internal),
50+
NVME_INFO_ERR_MISSING_CAP => NvmeInfoError::MissingCap(internal),
51+
NVME_INFO_ERR_BAD_LBA_FMT => NvmeInfoError::BadLbaFmt(internal),
52+
NVME_INFO_ERR_PERSIST_NVL => NvmeInfoError::PersistNvl(internal),
53+
NVME_INFO_ERR_BAD_FMT => NvmeInfoError::BadFmt(internal),
54+
NVME_INFO_ERR_BAD_FMT_DATA => NvmeInfoError::BadFmtData(internal),
55+
NVME_INFO_ERR_NS_INACTIVE => NvmeInfoError::NsInactive(internal),
56+
NVME_INFO_ERR_NS_NO_BLKDEV => NvmeInfoError::NsNoBlkdev(internal),
6657
// TODO map this to an error type so we don't crash someones program
6758
_ => unreachable!("Unknown Error"),
6859
}
@@ -113,7 +104,7 @@ impl<'ctrl> ControllerInfo<'ctrl> {
113104
unsafe { nvme_ctrl_info_nns(self.ctrl_info) }
114105
}
115106

116-
pub fn pci_vid(&self) -> Result<u16, ControllerInfoError> {
107+
pub fn pci_vid(&self) -> Result<u16, NvmeInfoError> {
117108
let mut vid = 0;
118109
match unsafe { nvme_ctrl_info_pci_vid(self.ctrl_info, &mut vid) } {
119110
true => Ok(vid),
@@ -125,10 +116,7 @@ impl<'ctrl> ControllerInfo<'ctrl> {
125116
unsafe { nvme_ctrl_info_nformats(self.ctrl_info) }
126117
}
127118

128-
fn nvm_lba_fmt(
129-
&self,
130-
index: u32,
131-
) -> Result<LbaFormat<'_>, ControllerInfoError> {
119+
fn nvm_lba_fmt(&self, index: u32) -> Result<LbaFormat<'_>, NvmeInfoError> {
132120
let mut lba: *const nvme_nvm_lba_fmt_t = std::ptr::null_mut();
133121
if !unsafe { nvme_ctrl_info_format(self.ctrl_info, index, &mut lba) } {
134122
return Err(self.fatal_context(format!(
@@ -138,15 +126,13 @@ impl<'ctrl> ControllerInfo<'ctrl> {
138126
Ok(unsafe { LbaFormat::from_raw(lba) })
139127
}
140128

141-
pub fn lba_formats(
142-
&self,
143-
) -> Vec<Result<LbaFormat<'_>, ControllerInfoError>> {
129+
pub fn lba_formats(&self) -> Vec<Result<LbaFormat<'_>, NvmeInfoError>> {
144130
(0..self.nformats()).map(|i| self.nvm_lba_fmt(i)).collect()
145131
}
146132
}
147133

148134
impl<'ctrl> LibraryError for ControllerInfo<'ctrl> {
149-
type Error = ControllerInfoError;
135+
type Error = NvmeInfoError;
150136

151137
fn get_errmsg(&self) -> String {
152138
let errmsg = unsafe { nvme_ctrl_info_errmsg(self.ctrl_info) };
@@ -158,7 +144,7 @@ impl<'ctrl> LibraryError for ControllerInfo<'ctrl> {
158144
}
159145

160146
fn to_error(&self, internal: InternalError) -> Self::Error {
161-
ControllerInfoError::from_raw_with_internal_error(
147+
NvmeInfoError::from_raw_with_internal_error(
162148
unsafe { nvme_ctrl_info_err(self.ctrl_info) },
163149
internal,
164150
)

libnvme/src/lba.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{controller_info::ControllerInfo, util::FfiPtr};
88

99
use libnvme_sys::nvme::*;
1010

11+
#[derive(Debug)]
1112
pub enum Performance {
1213
Best,
1314
Better,
@@ -30,7 +31,8 @@ impl From<u32> for Performance {
3031

3132
pub struct LbaFormat<'info> {
3233
lba: *const nvme_nvm_lba_fmt_t,
33-
_phantom: PhantomData<&'info ControllerInfo<'info>>,
34+
// This is tied to ControllerInfo or NamespaceInfo
35+
_phantom: PhantomData<&'info ()>,
3436
}
3537

3638
impl<'info> LbaFormat<'info> {

libnvme/src/namespace.rs

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
use crate::{controller::Controller, error::LibraryError, NvmeError};
5+
use std::ffi::CStr;
6+
7+
use crate::{
8+
controller::Controller,
9+
controller_info::NvmeInfoError,
10+
error::{InternalError, LibraryError},
11+
lba::LbaFormat,
12+
util::FfiPtr,
13+
NvmeError,
14+
};
615

716
use libnvme_sys::nvme::*;
817

@@ -106,6 +115,16 @@ impl<'a> Drop for Namespace<'a> {
106115
}
107116

108117
impl<'a> Namespace<'a> {
118+
pub fn get_info(&self) -> Result<NamespaceInfo, NvmeError> {
119+
let mut nvme_ns_info: *mut nvme_ns_info_t = std::ptr::null_mut();
120+
match unsafe { nvme_ns_info_snap(self.inner, &mut nvme_ns_info) } {
121+
true => Ok(unsafe { NamespaceInfo::from_raw(nvme_ns_info) }),
122+
false => Err(self
123+
.controller
124+
.fatal_context("failed to get ns info snapshot")),
125+
}
126+
}
127+
109128
pub fn blkdev_attach(&self) -> Result<(), NvmeError> {
110129
match unsafe { nvme_ns_bd_attach(self.inner) } {
111130
true => Ok(()),
@@ -124,3 +143,51 @@ impl<'a> Namespace<'a> {
124143
}
125144
}
126145
}
146+
147+
pub struct NamespaceInfo(*mut nvme_ns_info_t);
148+
149+
impl Drop for NamespaceInfo {
150+
fn drop(&mut self) {
151+
unsafe { nvme_ns_info_free(self.0) }
152+
}
153+
}
154+
155+
impl NamespaceInfo {
156+
pub fn current_format(&self) -> Result<LbaFormat, NvmeInfoError> {
157+
let mut lba: *const nvme_nvm_lba_fmt_t = std::ptr::null_mut();
158+
match unsafe { nvme_ns_info_curformat(self.0, &mut lba) } {
159+
true => Ok(unsafe { LbaFormat::from_raw(lba) }),
160+
false => Err(self.fatal_context(
161+
"failed to get current format of NVMe namespace",
162+
)),
163+
}
164+
}
165+
}
166+
167+
impl LibraryError for NamespaceInfo {
168+
type Error = NvmeInfoError;
169+
170+
fn get_errmsg(&self) -> String {
171+
let errmsg = unsafe { nvme_ns_info_errmsg(self.0) };
172+
unsafe { CStr::from_ptr(errmsg) }.to_string_lossy().to_string()
173+
}
174+
175+
fn get_syserr(&self) -> i32 {
176+
unsafe { nvme_ns_info_syserr(self.0) }
177+
}
178+
179+
fn to_error(&self, internal: InternalError) -> Self::Error {
180+
NvmeInfoError::from_raw_with_internal_error(
181+
unsafe { nvme_ns_info_err(self.0) },
182+
internal,
183+
)
184+
}
185+
}
186+
187+
impl FfiPtr for NamespaceInfo {
188+
type Ptr = *mut nvme_ns_info_t;
189+
190+
unsafe fn from_raw(ptr: Self::Ptr) -> Self {
191+
NamespaceInfo(ptr)
192+
}
193+
}

0 commit comments

Comments
 (0)