Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for namespace info #2

Merged
merged 1 commit into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libnvme-sys/header-check/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ fn main() {
"nvme_ns_iter" => true,
"nvme_ns_disc" => true,
"nvme_ns" => true,
"nvme_ns_info" => true,
"nvme_nvm_lba_fmt" => true,
"nvme_format_req" => true,
"di_node" => true,
Expand All @@ -59,6 +60,7 @@ fn main() {
"nvme_ns_iter_t" => true,
"nvme_ns_disc_t" => true,
"nvme_ns_t" => true,
"nvme_ns_info_t" => true,
"nvme_nvm_lba_fmt_t" => true,
"nvme_format_req_t" => true,
"di_node_t" => true,
Expand Down
15 changes: 15 additions & 0 deletions libnvme-sys/src/nvme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ opaque_type!(nvme_ctrl_info, nvme_ctrl_info_t);
opaque_type!(nvme_ns_iter, nvme_ns_iter_t);
opaque_type!(nvme_ns_disc, nvme_ns_disc_t);
opaque_type!(nvme_ns, nvme_ns_t);
opaque_type!(nvme_ns_info, nvme_ns_info_t);
opaque_type!(nvme_nvm_lba_fmt, nvme_nvm_lba_fmt_t);
opaque_type!(nvme_format_req, nvme_format_req_t);

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

// NVMe Namespace information.
pub fn nvme_ns_info_snap(
arg1: *mut nvme_ns_t,
arg2: *mut *mut nvme_ns_info_t,
) -> bool;
pub fn nvme_ns_info_free(arg1: *mut nvme_ns_info_t);
pub fn nvme_ns_info_err(arg1: *mut nvme_ns_info_t) -> nvme_info_err_t;
pub fn nvme_ns_info_errmsg(arg1: *mut nvme_ns_info_t) -> *const c_char;
pub fn nvme_ns_info_syserr(arg1: *mut nvme_ns_info_t) -> c_int;
pub fn nvme_ns_info_curformat(
arg1: *mut nvme_ns_info_t,
arg2: *mut *const nvme_nvm_lba_fmt,
) -> bool;

// Controller Locking.
pub fn nvme_ctrl_lock(
arg1: *mut nvme_ctrl_t,
Expand Down
56 changes: 21 additions & 35 deletions libnvme/src/controller_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
};

#[derive(Debug, Error)]
pub enum ControllerInfoError {
pub enum NvmeInfoError {
#[error(transparent)]
Ok(InternalError),
#[error(transparent)]
Expand All @@ -38,31 +38,22 @@ pub enum ControllerInfoError {
NsNoBlkdev(InternalError),
}

impl ControllerInfoError {
fn from_raw_with_internal_error(raw: u32, internal: InternalError) -> Self {
impl NvmeInfoError {
pub(crate) fn from_raw_with_internal_error(
raw: u32,
internal: InternalError,
) -> Self {
match raw {
NVME_INFO_ERR_OK => ControllerInfoError::Ok(internal),
NVME_INFO_ERR_TRANSPORT => ControllerInfoError::Transport(internal),
NVME_INFO_ERR_VERSION => ControllerInfoError::Version(internal),
NVME_INFO_ERR_MISSING_CAP => {
ControllerInfoError::MissingCap(internal)
}
NVME_INFO_ERR_BAD_LBA_FMT => {
ControllerInfoError::BadLbaFmt(internal)
}
NVME_INFO_ERR_PERSIST_NVL => {
ControllerInfoError::PersistNvl(internal)
}
NVME_INFO_ERR_BAD_FMT => ControllerInfoError::BadFmt(internal),
NVME_INFO_ERR_BAD_FMT_DATA => {
ControllerInfoError::BadFmtData(internal)
}
NVME_INFO_ERR_NS_INACTIVE => {
ControllerInfoError::NsInactive(internal)
}
NVME_INFO_ERR_NS_NO_BLKDEV => {
ControllerInfoError::NsNoBlkdev(internal)
}
NVME_INFO_ERR_OK => NvmeInfoError::Ok(internal),
NVME_INFO_ERR_TRANSPORT => NvmeInfoError::Transport(internal),
NVME_INFO_ERR_VERSION => NvmeInfoError::Version(internal),
NVME_INFO_ERR_MISSING_CAP => NvmeInfoError::MissingCap(internal),
NVME_INFO_ERR_BAD_LBA_FMT => NvmeInfoError::BadLbaFmt(internal),
NVME_INFO_ERR_PERSIST_NVL => NvmeInfoError::PersistNvl(internal),
NVME_INFO_ERR_BAD_FMT => NvmeInfoError::BadFmt(internal),
NVME_INFO_ERR_BAD_FMT_DATA => NvmeInfoError::BadFmtData(internal),
NVME_INFO_ERR_NS_INACTIVE => NvmeInfoError::NsInactive(internal),
NVME_INFO_ERR_NS_NO_BLKDEV => NvmeInfoError::NsNoBlkdev(internal),
// TODO map this to an error type so we don't crash someones program
_ => unreachable!("Unknown Error"),
}
Expand Down Expand Up @@ -113,7 +104,7 @@ impl<'ctrl> ControllerInfo<'ctrl> {
unsafe { nvme_ctrl_info_nns(self.ctrl_info) }
}

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

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

pub fn lba_formats(
&self,
) -> Vec<Result<LbaFormat<'_>, ControllerInfoError>> {
pub fn lba_formats(&self) -> Vec<Result<LbaFormat<'_>, NvmeInfoError>> {
(0..self.nformats()).map(|i| self.nvm_lba_fmt(i)).collect()
}
}

impl<'ctrl> LibraryError for ControllerInfo<'ctrl> {
type Error = ControllerInfoError;
type Error = NvmeInfoError;

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

fn to_error(&self, internal: InternalError) -> Self::Error {
ControllerInfoError::from_raw_with_internal_error(
NvmeInfoError::from_raw_with_internal_error(
unsafe { nvme_ctrl_info_err(self.ctrl_info) },
internal,
)
Expand Down
4 changes: 3 additions & 1 deletion libnvme/src/lba.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{controller_info::ControllerInfo, util::FfiPtr};

use libnvme_sys::nvme::*;

#[derive(Debug)]
pub enum Performance {
Best,
Better,
Expand All @@ -30,7 +31,8 @@ impl From<u32> for Performance {

pub struct LbaFormat<'info> {
lba: *const nvme_nvm_lba_fmt_t,
_phantom: PhantomData<&'info ControllerInfo<'info>>,
// This is tied to ControllerInfo or NamespaceInfo
_phantom: PhantomData<&'info ()>,
}

impl<'info> LbaFormat<'info> {
Expand Down
69 changes: 68 additions & 1 deletion libnvme/src/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use crate::{controller::Controller, error::LibraryError, NvmeError};
use std::ffi::CStr;

use crate::{
controller::Controller,
controller_info::NvmeInfoError,
error::{InternalError, LibraryError},
lba::LbaFormat,
util::FfiPtr,
NvmeError,
};

use libnvme_sys::nvme::*;

Expand Down Expand Up @@ -106,6 +115,16 @@ impl<'a> Drop for Namespace<'a> {
}

impl<'a> Namespace<'a> {
pub fn get_info(&self) -> Result<NamespaceInfo, NvmeError> {
let mut nvme_ns_info: *mut nvme_ns_info_t = std::ptr::null_mut();
match unsafe { nvme_ns_info_snap(self.inner, &mut nvme_ns_info) } {
true => Ok(unsafe { NamespaceInfo::from_raw(nvme_ns_info) }),
false => Err(self
.controller
.fatal_context("failed to get ns info snapshot")),
}
}

pub fn blkdev_attach(&self) -> Result<(), NvmeError> {
match unsafe { nvme_ns_bd_attach(self.inner) } {
true => Ok(()),
Expand All @@ -124,3 +143,51 @@ impl<'a> Namespace<'a> {
}
}
}

pub struct NamespaceInfo(*mut nvme_ns_info_t);

impl Drop for NamespaceInfo {
fn drop(&mut self) {
unsafe { nvme_ns_info_free(self.0) }
}
}

impl NamespaceInfo {
pub fn current_format(&self) -> Result<LbaFormat, NvmeInfoError> {
let mut lba: *const nvme_nvm_lba_fmt_t = std::ptr::null_mut();
match unsafe { nvme_ns_info_curformat(self.0, &mut lba) } {
true => Ok(unsafe { LbaFormat::from_raw(lba) }),
false => Err(self.fatal_context(
"failed to get current format of NVMe namespace",
)),
}
}
}

impl LibraryError for NamespaceInfo {
type Error = NvmeInfoError;

fn get_errmsg(&self) -> String {
let errmsg = unsafe { nvme_ns_info_errmsg(self.0) };
unsafe { CStr::from_ptr(errmsg) }.to_string_lossy().to_string()
}

fn get_syserr(&self) -> i32 {
unsafe { nvme_ns_info_syserr(self.0) }
}

fn to_error(&self, internal: InternalError) -> Self::Error {
NvmeInfoError::from_raw_with_internal_error(
unsafe { nvme_ns_info_err(self.0) },
internal,
)
}
}

impl FfiPtr for NamespaceInfo {
type Ptr = *mut nvme_ns_info_t;

unsafe fn from_raw(ptr: Self::Ptr) -> Self {
NamespaceInfo(ptr)
}
}