sgutils2: use enum for ScsiError

This avoids string allocation when we return SenseInfo.
This commit is contained in:
Dietmar Maurer 2021-03-27 15:57:48 +01:00
parent 03eac20b87
commit cf1e117fc7
2 changed files with 16 additions and 12 deletions

View File

@ -28,6 +28,7 @@ use crate::{
SENSE_KEY_UNIT_ATTENTION, SENSE_KEY_UNIT_ATTENTION,
SENSE_KEY_NOT_READY, SENSE_KEY_NOT_READY,
InquiryInfo, InquiryInfo,
ScsiError,
scsi_ascii_to_string, scsi_ascii_to_string,
scsi_inquiry, scsi_inquiry,
}, },
@ -103,7 +104,7 @@ fn execute_scsi_command<F: AsRawFd>(
if !retry { if !retry {
bail!("{} failed: {}", error_prefix, err); bail!("{} failed: {}", error_prefix, err);
} }
if let Some(ref sense) = err.sense { if let ScsiError::Sense(ref sense) = err {
if sense.sense_key == SENSE_KEY_NO_SENSE || if sense.sense_key == SENSE_KEY_NO_SENSE ||
sense.sense_key == SENSE_KEY_RECOVERED_ERROR || sense.sense_key == SENSE_KEY_RECOVERED_ERROR ||

View File

@ -44,32 +44,38 @@ impl ToString for SenseInfo {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct ScsiError { pub enum ScsiError {
pub error: Error, Error(Error),
pub sense: Option<SenseInfo>, Sense(SenseInfo),
} }
impl std::fmt::Display for ScsiError { impl std::fmt::Display for ScsiError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.error) match self {
ScsiError::Error(err) => write!(f, "{}", err),
ScsiError::Sense(sense) => write!(f, "{}", sense.to_string()),
}
} }
} }
impl std::error::Error for ScsiError { impl std::error::Error for ScsiError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.error.source() match self {
ScsiError::Error(err) => err.source(),
ScsiError::Sense(_) => None,
}
} }
} }
impl From<anyhow::Error> for ScsiError { impl From<anyhow::Error> for ScsiError {
fn from(error: anyhow::Error) -> Self { fn from(error: anyhow::Error) -> Self {
Self { error, sense: None } Self::Error(error)
} }
} }
impl From<std::io::Error> for ScsiError { impl From<std::io::Error> for ScsiError {
fn from(error: std::io::Error) -> Self { fn from(error: std::io::Error) -> Self {
Self { error: error.into(), sense: None } Self::Error(error.into())
} }
} }
@ -483,10 +489,7 @@ impl <'a, F: AsRawFd> SgRaw<'a, F> {
} }
}; };
return Err(ScsiError { return Err(ScsiError::Sense(sense));
error: format_err!("{}", sense.to_string()),
sense: Some(sense),
});
} }
SCSI_PT_RESULT_TRANSPORT_ERR => return Err(format_err!("scsi command failed: transport error").into()), SCSI_PT_RESULT_TRANSPORT_ERR => return Err(format_err!("scsi command failed: transport error").into()),
SCSI_PT_RESULT_OS_ERR => { SCSI_PT_RESULT_OS_ERR => {