Merge branch 'master' of ssh://proxdev.maurer-it.com/rust/proxmox-backup

This commit is contained in:
Dietmar Maurer
2021-01-21 10:56:52 +01:00
122 changed files with 521 additions and 614 deletions

View File

@ -187,11 +187,9 @@ pub trait MediaChange {
if let ElementStatus::Empty = element_status {
to = Some(i as u64 + 1);
}
} else {
if let ElementStatus::VolumeTag(ref tag) = element_status {
if tag == label_text {
from = Some(i as u64 + 1);
}
} else if let ElementStatus::VolumeTag(ref tag) = element_status {
if tag == label_text {
from = Some(i as u64 + 1);
}
}
}

View File

@ -58,13 +58,12 @@ fn parse_drive_status(i: &str) -> IResult<&str, DriveStatus> {
let mut loaded_slot = None;
if i.starts_with("Empty") {
return Ok((&i[5..], DriveStatus { loaded_slot, status: ElementStatus::Empty }));
if let Some(empty) = i.strip_suffix("Empty") {
return Ok((empty, DriveStatus { loaded_slot, status: ElementStatus::Empty }));
}
let (mut i, _) = tag("Full (")(i)?;
if i.starts_with("Storage Element ") {
let n = &i[16..];
if let Some(n) = i.strip_prefix("Storage Element ") {
let (n, id) = parse_u64(n)?;
loaded_slot = Some(id);
let (n, _) = tag(" Loaded")(n)?;
@ -76,8 +75,7 @@ fn parse_drive_status(i: &str) -> IResult<&str, DriveStatus> {
let (i, _) = tag(")")(i)?;
if i.starts_with(":VolumeTag = ") {
let i = &i[13..];
if let Some(i) = i.strip_prefix(":VolumeTag = ") {
let (i, tag) = take_while(|c| !(c == ' ' || c == ':' || c == '\n'))(i)?;
let (i, _) = take_while(|c| c != '\n')(i)?; // skip to eol
return Ok((i, DriveStatus { loaded_slot, status: ElementStatus::VolumeTag(tag.to_string()) }));
@ -89,14 +87,11 @@ fn parse_drive_status(i: &str) -> IResult<&str, DriveStatus> {
}
fn parse_slot_status(i: &str) -> IResult<&str, ElementStatus> {
if i.starts_with("Empty") {
return Ok((&i[5..], ElementStatus::Empty));
if let Some(empty) = i.strip_prefix("Empty") {
return Ok((empty, ElementStatus::Empty));
}
if i.starts_with("Full ") {
let mut n = &i[5..];
if n.starts_with(":VolumeTag=") {
n = &n[11..];
if let Some(n) = i.strip_prefix("Full ") {
if let Some(n) = n.strip_prefix(":VolumeTag=") {
let (n, tag) = take_while(|c| !(c == ' ' || c == ':' || c == '\n'))(n)?;
let (n, _) = take_while(|c| c != '\n')(n)?; // skip to eol
return Ok((n, ElementStatus::VolumeTag(tag.to_string())));

View File

@ -62,15 +62,11 @@ impl <'a> ChunkArchiveWriter<'a> {
}
fn write_all(&mut self, data: &[u8]) -> Result<bool, std::io::Error> {
let result = match self.writer {
Some(ref mut writer) => {
let leom = writer.write_all(data)?;
Ok(leom)
}
match self.writer {
Some(ref mut writer) => writer.write_all(data),
None => proxmox::io_bail!(
"detected write after archive finished - internal error"),
};
result
}
}
/// Write chunk into archive.

View File

@ -24,10 +24,7 @@ pub fn has_encryption<F: AsRawFd>(
Ok(data) => data,
Err(_) => return false,
};
match decode_spin_data_encryption_caps(&data) {
Ok(_) => true,
Err(_) => false,
}
decode_spin_data_encryption_caps(&data).is_ok()
}
/// Set or clear encryption key

View File

@ -85,12 +85,12 @@ pub fn linux_tape_changer_list() -> Vec<TapeDeviceInfo> {
let vendor = device.property_value("ID_VENDOR")
.map(std::ffi::OsString::from)
.and_then(|s| if let Ok(s) = s.into_string() { Some(s) } else { None })
.unwrap_or(String::from("unknown"));
.unwrap_or_else(|| String::from("unknown"));
let model = device.property_value("ID_MODEL")
.map(std::ffi::OsString::from)
.and_then(|s| if let Ok(s) = s.into_string() { Some(s) } else { None })
.unwrap_or(String::from("unknown"));
.unwrap_or_else(|| String::from("unknown"));
let dev_path = format!("/dev/tape/by-id/scsi-{}", serial);
@ -166,12 +166,12 @@ pub fn linux_tape_device_list() -> Vec<TapeDeviceInfo> {
let vendor = device.property_value("ID_VENDOR")
.map(std::ffi::OsString::from)
.and_then(|s| if let Ok(s) = s.into_string() { Some(s) } else { None })
.unwrap_or(String::from("unknown"));
.unwrap_or_else(|| String::from("unknown"));
let model = device.property_value("ID_MODEL")
.map(std::ffi::OsString::from)
.and_then(|s| if let Ok(s) = s.into_string() { Some(s) } else { None })
.unwrap_or(String::from("unknown"));
.unwrap_or_else(|| String::from("unknown"));
let dev_path = format!("/dev/tape/by-id/scsi-{}-nst", serial);

View File

@ -98,16 +98,14 @@ impl LinuxTapeDrive {
if drive_status.blocksize == 0 {
// device is variable block size - OK
} else {
if drive_status.blocksize != PROXMOX_TAPE_BLOCK_SIZE as u32 {
eprintln!("device is in fixed block size mode with wrong size ({} bytes)", drive_status.blocksize);
eprintln!("trying to set variable block size mode...");
if handle.set_block_size(0).is_err() {
bail!("set variable block size mod failed - device uses wrong blocksize.");
}
} else {
// device is in fixed block size mode with correct block size
} else if drive_status.blocksize != PROXMOX_TAPE_BLOCK_SIZE as u32 {
eprintln!("device is in fixed block size mode with wrong size ({} bytes)", drive_status.blocksize);
eprintln!("trying to set variable block size mode...");
if handle.set_block_size(0).is_err() {
bail!("set variable block size mod failed - device uses wrong blocksize.");
}
} else {
// device is in fixed block size mode with correct block size
}
// Only root can set driver options, so we cannot
@ -528,7 +526,7 @@ impl TapeDriver for LinuxTapeHandle {
let result: Result<u64, String> = serde_json::from_str(&output)?;
result
.map_err(|err| format_err!("{}", err))
.map(|bits| TapeAlertFlags::from_bits_truncate(bits))
.map(TapeAlertFlags::from_bits_truncate)
}
/// Set or clear encryption key

View File

@ -32,7 +32,7 @@ enum MamFormat {
DEC,
}
static MAM_ATTRIBUTES: &'static [ (u16, u16, MamFormat, &'static str) ] = &[
static MAM_ATTRIBUTES: &[ (u16, u16, MamFormat, &str) ] = &[
(0x00_00, 8, MamFormat::DEC, "Remaining Capacity In Partition"),
(0x00_01, 8, MamFormat::DEC, "Maximum Capacity In Partition"),
(0x00_02, 8, MamFormat::DEC, "Tapealert Flags"),

View File

@ -258,13 +258,13 @@ pub fn required_media_changer(
) -> Result<(Box<dyn MediaChange>, String), Error> {
match media_changer(config, drive) {
Ok(Some(result)) => {
return Ok(result);
Ok(result)
}
Ok(None) => {
bail!("drive '{}' has no associated changer device", drive);
},
Err(err) => {
return Err(err);
Err(err)
}
}
}
@ -339,7 +339,7 @@ pub fn request_and_load_media(
let media_id = check_label(handle.as_mut(), &label.uuid)?;
return Ok((handle, media_id));
Ok((handle, media_id))
}
"linux" => {
let drive_config = LinuxTapeDrive::deserialize(config)?;
@ -390,20 +390,18 @@ pub fn request_and_load_media(
media_id.label.uuid.to_string(),
));
return Ok((Box::new(handle), media_id));
} else {
if Some(media_id.label.uuid.clone()) != last_media_uuid {
worker.log(format!(
"wrong media label {} ({})",
media_id.label.label_text,
media_id.label.uuid.to_string(),
));
last_media_uuid = Some(media_id.label.uuid);
}
} else if Some(media_id.label.uuid.clone()) != last_media_uuid {
worker.log(format!(
"wrong media label {} ({})",
media_id.label.label_text,
media_id.label.uuid.to_string(),
));
last_media_uuid = Some(media_id.label.uuid);
}
}
Ok((None, _)) => {
if last_media_uuid.is_some() {
worker.log(format!("found empty media without label (please label all tapes first)"));
worker.log("found empty media without label (please label all tapes first)".to_string());
last_media_uuid = None;
}
}

View File

@ -17,6 +17,7 @@ bitflags::bitflags!{
///
/// See LTO SCSI Reference LOG_SENSE - LP 2Eh: TapeAlerts
pub struct TapeAlertFlags: u64 {
#[allow(clippy::eq_op)]
const READ_WARNING = 1 << (0x0001 -1);
const WRITE_WARNING = 1 << (0x0002 -1);
const HARD_ERROR = 1 << (0x0003 -1);

View File

@ -168,8 +168,8 @@ impl VirtualTapeHandle {
if path.is_file() && path.extension() == Some(std::ffi::OsStr::new("json")) {
if let Some(name) = path.file_stem() {
if let Some(name) = name.to_str() {
if name.starts_with("tape-") {
list.push(name[5..].to_string());
if let Some(label) = name.strip_prefix("tape-") {
list.push(label.to_string());
}
}
}

View File

@ -95,19 +95,16 @@ fn decode_volume_statistics(data: &[u8]) -> Result<Lp17VolumeStatistics, Error>
let read_be_counter = |reader: &mut &[u8], len: u8| {
let len = len as usize;
if len == 0 || len > 8 {
bail!("invalid conter size '{}'", len);
}
let mut buffer = [0u8; 8];
reader.read_exact(&mut buffer[..len])?;
let mut value: u64 = 0;
for i in 0..len {
value = value << 8;
value = value | buffer[i] as u64;
}
let value = buffer
.iter()
.take(len)
.fold(0, |value, curr| (value << 8) | *curr as u64);
Ok(value)
};

View File

@ -81,10 +81,8 @@ impl <R: Read> BlockedReader<R> {
if size > buffer.payload.len() {
proxmox::io_bail!("detected tape block with wrong payload size ({} > {}", size, buffer.payload.len());
} else if size == 0 {
if !found_end_marker{
proxmox::io_bail!("detected tape block with zero payload size");
}
} else if size == 0 && !found_end_marker {
proxmox::io_bail!("detected tape block with zero payload size");
}
@ -179,7 +177,7 @@ impl <R: Read> Read for BlockedReader<R> {
}
if rest <= 0 {
return Ok(0);
Ok(0)
} else {
let copy_len = if (buffer.len() as isize) < rest {
buffer.len()
@ -189,7 +187,7 @@ impl <R: Read> Read for BlockedReader<R> {
buffer[..copy_len].copy_from_slice(
&self.buffer.payload[self.read_pos..(self.read_pos + copy_len)]);
self.read_pos += copy_len;
return Ok(copy_len);
Ok(copy_len)
}
}
}

View File

@ -77,7 +77,7 @@ impl <W: Write> BlockedWriter<W> {
self.bytes_written += BlockHeader::SIZE;
} else {
self.buffer_pos = self.buffer_pos + bytes;
self.buffer_pos += bytes;
}
Ok(bytes)

View File

@ -50,7 +50,7 @@ impl SnapshotReader {
}
};
let mut client_log_path = snapshot_path.clone();
let mut client_log_path = snapshot_path;
client_log_path.push(CLIENT_LOG_BLOB_NAME);
let mut file_list = Vec::new();

View File

@ -215,12 +215,13 @@ impl Inventory {
/// find media by label_text
pub fn find_media_by_label_text(&self, label_text: &str) -> Option<&MediaId> {
for (_uuid, entry) in &self.map {
self.map.values().find_map(|entry| {
if entry.id.label.label_text == label_text {
return Some(&entry.id);
Some(&entry.id)
} else {
None
}
}
None
})
}
/// Lookup media pool
@ -245,7 +246,7 @@ impl Inventory {
pub fn list_pool_media(&self, pool: &str) -> Vec<MediaId> {
let mut list = Vec::new();
for (_uuid, entry) in &self.map {
for entry in self.map.values() {
match entry.id.media_set_label {
None => continue, // not assigned to any pool
Some(ref set) => {
@ -272,7 +273,7 @@ impl Inventory {
pub fn list_used_media(&self) -> Vec<MediaId> {
let mut list = Vec::new();
for (_uuid, entry) in &self.map {
for entry in self.map.values() {
match entry.id.media_set_label {
None => continue, // not assigned to any pool
Some(ref set) => {
@ -288,19 +289,17 @@ impl Inventory {
/// List media not assigned to any pool
pub fn list_unassigned_media(&self) -> Vec<MediaId> {
let mut list = Vec::new();
for (_uuid, entry) in &self.map {
self.map.values().filter_map(|entry|
if entry.id.media_set_label.is_none() {
list.push(entry.id.clone());
Some(entry.id.clone())
} else {
None
}
}
list
).collect()
}
pub fn media_set_start_time(&self, media_set_uuid: &Uuid) -> Option<i64> {
self.media_set_start_times.get(media_set_uuid).map(|t| *t)
self.media_set_start_times.get(media_set_uuid).copied()
}
/// Lookup media set pool
@ -383,7 +382,7 @@ impl Inventory {
let set_list = self.map.values()
.filter_map(|entry| entry.id.media_set_label.as_ref())
.filter(|set| &set.pool == &pool && set.uuid.as_ref() != [0u8;16]);
.filter(|set| set.pool == pool && set.uuid.as_ref() != [0u8;16]);
for set in set_list {
match last_set {
@ -406,7 +405,7 @@ impl Inventory {
// consistency check - must be the only set with that ctime
let set_list = self.map.values()
.filter_map(|entry| entry.id.media_set_label.as_ref())
.filter(|set| &set.pool == &pool && set.uuid.as_ref() != [0u8;16]);
.filter(|set| set.pool == pool && set.uuid.as_ref() != [0u8;16]);
for set in set_list {
if set.uuid != uuid && set.ctime >= ctime { // should not happen
@ -437,7 +436,7 @@ impl Inventory {
let set_list = self.map.values()
.filter_map(|entry| entry.id.media_set_label.as_ref())
.filter(|set| (&set.uuid != media_set_uuid) && (&set.pool == &pool));
.filter(|set| (&set.uuid != media_set_uuid) && (set.pool == pool));
let mut next_ctime = None;
@ -522,7 +521,7 @@ impl Inventory {
) -> Result<String, Error> {
if let Some(ctime) = self.media_set_start_time(media_set_uuid) {
let mut template = template.unwrap_or(String::from("%c"));
let mut template = template.unwrap_or_else(|| String::from("%c"));
template = template.replace("%id%", &media_set_uuid.to_string());
proxmox::tools::time::strftime_local(&template, ctime)
} else {
@ -675,20 +674,18 @@ impl Inventory {
for (uuid, entry) in self.map.iter_mut() {
if let Some(changer_name) = online_map.lookup_changer(uuid) {
entry.location = Some(MediaLocation::Online(changer_name.to_string()));
} else {
if let Some(MediaLocation::Online(ref changer_name)) = entry.location {
match online_map.online_map(changer_name) {
None => {
// no such changer device
entry.location = Some(MediaLocation::Offline);
}
Some(None) => {
// got no info - do nothing
}
Some(Some(_)) => {
// media changer changed
entry.location = Some(MediaLocation::Offline);
}
} else if let Some(MediaLocation::Online(ref changer_name)) = entry.location {
match online_map.online_map(changer_name) {
None => {
// no such changer device
entry.location = Some(MediaLocation::Offline);
}
Some(None) => {
// got no info - do nothing
}
Some(Some(_)) => {
// media changer changed
entry.location = Some(MediaLocation::Offline);
}
}
}

View File

@ -323,7 +323,7 @@ impl MediaCatalog {
/// Returns the chunk archive file number
pub fn lookup_snapshot(&self, snapshot: &str) -> Option<u64> {
self.snapshot_index.get(snapshot).map(|n| *n)
self.snapshot_index.get(snapshot).copied()
}
/// Test if the catalog already contain a chunk
@ -333,7 +333,7 @@ impl MediaCatalog {
/// Returns the chunk archive file number
pub fn lookup_chunk(&self, digest: &[u8;32]) -> Option<u64> {
self.chunk_index.get(digest).map(|n| *n)
self.chunk_index.get(digest).copied()
}
fn check_register_label(&self, file_number: u64) -> Result<(), Error> {

View File

@ -89,9 +89,9 @@ impl MediaPool {
use_offline_media: bool,
) -> Result<Self, Error> {
let allocation = config.allocation.clone().unwrap_or(String::from("continue")).parse()?;
let allocation = config.allocation.clone().unwrap_or_else(|| String::from("continue")).parse()?;
let retention = config.retention.clone().unwrap_or(String::from("keep")).parse()?;
let retention = config.retention.clone().unwrap_or_else(|| String::from("keep")).parse()?;
let encrypt_fingerprint = match config.encrypt {
Some(ref fingerprint) => Some(fingerprint.parse()?),

View File

@ -173,7 +173,7 @@ pub fn update_changer_online_status(
drive_config: &SectionConfigData,
inventory: &mut Inventory,
changer_name: &str,
label_text_list: &Vec<String>,
label_text_list: &[String],
) -> Result<(), Error> {
let mut online_map = OnlineStatusMap::new(drive_config)?;

View File

@ -159,11 +159,9 @@ impl PoolWriter {
}
}
} else {
if let Some(mut status) = status {
worker.log("standalone drive - ejecting media instead of export");
status.drive.eject_media()?;
}
} else if let Some(mut status) = status {
worker.log("standalone drive - ejecting media instead of export");
status.drive.eject_media()?;
}
Ok(())
@ -303,7 +301,7 @@ impl PoolWriter {
status.bytes_written += bytes_written;
let request_sync = if status.bytes_written >= COMMIT_BLOCK_SIZE { true } else { false };
let request_sync = status.bytes_written >= COMMIT_BLOCK_SIZE;
if !done || request_sync {
status.commit()?;
@ -361,7 +359,7 @@ impl PoolWriter {
(bytes_written as f64)/(1024.0*1024.0*elapsed),
));
let request_sync = if status.bytes_written >= COMMIT_BLOCK_SIZE { true } else { false };
let request_sync = status.bytes_written >= COMMIT_BLOCK_SIZE;
// register chunks in media_catalog
status.catalog.start_chunk_archive(content_uuid, current_file_number)?;
@ -426,7 +424,7 @@ fn write_chunk_archive<'a>(
}
if writer.bytes_written() > max_size {
worker.log(format!("Chunk Archive max size reached, closing archive"));
worker.log("Chunk Archive max size reached, closing archive".to_string());
break;
}
}
@ -469,7 +467,7 @@ fn update_media_set_label(
match old_set {
None => {
worker.log(format!("wrinting new media set label"));
worker.log("wrinting new media set label".to_string());
drive.write_media_set_label(new_set, key_config.as_ref())?;
media_catalog = MediaCatalog::overwrite(status_path, media_id, false)?;
}

View File

@ -191,17 +191,17 @@ impl <'a, F: AsRawFd> SgRaw<'a, F> {
}
// todo: what about sense data?
let _sense_len = unsafe { get_scsi_pt_sense_len(&mut *ptvp) };
let _sense_len = unsafe { get_scsi_pt_sense_len(&*ptvp) };
let status = unsafe { get_scsi_pt_status_response(&mut *ptvp) };
let status = unsafe { get_scsi_pt_status_response(&*ptvp) };
if status != 0 {
// toto: improve error reporting
bail!("unknown scsi error - status response {}", status);
}
let data_len = self.buffer.len() -
(unsafe { get_scsi_pt_resid(&mut *ptvp) } as usize);
if data_len <= 0 {
(unsafe { get_scsi_pt_resid(&*ptvp) } as usize);
if data_len == 0 {
bail!("do_scsi_pt failed - no data received");
}
@ -248,9 +248,9 @@ impl <'a, F: AsRawFd> SgRaw<'a, F> {
}
// todo: what about sense data?
let _sense_len = unsafe { get_scsi_pt_sense_len(&mut *ptvp) };
let _sense_len = unsafe { get_scsi_pt_sense_len(&*ptvp) };
let status = unsafe { get_scsi_pt_status_response(&mut *ptvp) };
let status = unsafe { get_scsi_pt_status_response(&*ptvp) };
if status != 0 {
// toto: improve error reporting
bail!("unknown scsi error - status response {}", status);