diff --git a/src/lib.rs b/src/lib.rs index 9d55340..bc8f8ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -747,7 +747,7 @@ where let mut objects = block.objects(); while let Some(meta_object) = objects.next(&mut self.medium).await? { match meta_object.state() { - ObjectState::Free => break, + ObjectState::Free | ObjectState::Corrupted => break, ObjectState::Allocated => break, ObjectState::Finalized => {} ObjectState::Deleted => continue, @@ -826,8 +826,8 @@ trait ObjectMover: Debug { while let Some(object) = iter.next(&mut storage.medium).await? { match object.state() { ObjectState::Free | ObjectState::Deleted => continue, - ObjectState::Allocated => { - log::warn!("Encountered an allocated object"); + ObjectState::Allocated | ObjectState::Corrupted => { + log::warn!("Encountered object in incorrect state"); // TODO: retry in a different object return Err(StorageError::InsufficientSpace); } diff --git a/src/ll/blocks.rs b/src/ll/blocks.rs index 6dd94fa..b6bb9ee 100644 --- a/src/ll/blocks.rs +++ b/src/ll/blocks.rs @@ -304,6 +304,7 @@ impl IndexedBlockInfo { match object.state() { ObjectState::Allocated | ObjectState::Deleted => deleted += object.total_size(), ObjectState::Free | ObjectState::Finalized => {} + ObjectState::Corrupted => break, } } diff --git a/src/ll/objects.rs b/src/ll/objects.rs index 5302911..642c1cf 100644 --- a/src/ll/objects.rs +++ b/src/ll/objects.rs @@ -10,16 +10,19 @@ use crate::{ // Do not use 0xFF as it is reserved for the free state. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum ObjectType { + Free = 0xFF, FileMetadata = 0x8F, FileData = 0x8E, + Unknown = 0x00, } impl ObjectType { - fn parse(byte: u8) -> Option { + fn parse(byte: u8) -> Self { match byte { - v if v == Self::FileMetadata as u8 => Some(Self::FileMetadata), - v if v == Self::FileData as u8 => Some(Self::FileData), - _ => None, + v if v == Self::FileMetadata as u8 => Self::FileMetadata, + v if v == Self::FileData as u8 => Self::FileData, + 0xFF => Self::Free, + _ => Self::Unknown, } } } @@ -29,31 +32,32 @@ pub enum ObjectDataState { Untrusted = 0xFF, Valid = 0xF0, Deleted = 0x00, + Unknown, } impl ObjectDataState { - fn parse(byte: u8) -> Result { + fn parse(byte: u8) -> Self { match byte { - v if v == Self::Untrusted as u8 => Ok(Self::Untrusted), - v if v == Self::Valid as u8 => Ok(Self::Valid), - v if v == Self::Deleted as u8 => Ok(Self::Deleted), + v if v == Self::Untrusted as u8 => Self::Untrusted, + v if v == Self::Valid as u8 => Self::Valid, + v if v == Self::Deleted as u8 => Self::Deleted, _ => { log::warn!("Unknown object data state: 0x{byte:02X}"); - Err(StorageError::FsCorrupted) + Self::Unknown } } } - fn parse_pair(finalized_byte: u8, deleted_byte: u8) -> Result { + fn parse_pair(finalized_byte: u8, deleted_byte: u8) -> Self { match (finalized_byte, deleted_byte) { - (0xFF, 0xFF) => Ok(Self::Untrusted), - (0x00, 0xFF) => Ok(Self::Valid), - (0x00, 0x00) => Ok(Self::Deleted), + (0xFF, 0xFF) => Self::Untrusted, + (0x00, 0xFF) => Self::Valid, + (0x00, 0x00) => Self::Deleted, _ => { log::warn!( "Unknown object data state: (0x{finalized_byte:02X}, 0x{deleted_byte:02X})" ); - Err(StorageError::FsCorrupted) + Self::Unknown } } } @@ -73,6 +77,7 @@ impl From for ObjectState { ObjectDataState::Untrusted => Self::Allocated, ObjectDataState::Valid => Self::Finalized, ObjectDataState::Deleted => Self::Deleted, + ObjectDataState::Unknown => Self::Corrupted, }, } } @@ -101,7 +106,9 @@ impl CompositeObjectState { } let new_data_state = match new_state { - ObjectState::Free => unreachable!(), + ObjectState::Free | ObjectState::Corrupted => { + unreachable!() + } ObjectState::Allocated => ObjectDataState::Untrusted, ObjectState::Finalized => ObjectDataState::Valid, ObjectState::Deleted => ObjectDataState::Deleted, @@ -130,21 +137,17 @@ impl CompositeObjectState { medium.read(location.block, location.offset, buffer).await?; match ObjectType::parse(buffer[0]) { - Some(ty) => { + ObjectType::Free => Ok(Self::Free), + ty => { let data_state = match M::WRITE_GRANULARITY { - WriteGranularity::Bit => ObjectDataState::parse(buffer[1])?, + WriteGranularity::Bit => ObjectDataState::parse(buffer[1]), WriteGranularity::Word(w) => { - ObjectDataState::parse_pair(buffer[w], buffer[2 * w])? + ObjectDataState::parse_pair(buffer[w], buffer[2 * w]) } }; Ok(Self::Allocated(ty, data_state)) } - None if buffer[0] == 0xFF => Ok(Self::Free), - None => { - log::warn!("Unknown object type: 0x{:02X}", buffer[0]); - Err(StorageError::FsCorrupted) - } } } @@ -223,6 +226,7 @@ pub enum ObjectState { Allocated, Finalized, Deleted, + Corrupted, } impl ObjectState { @@ -360,8 +364,6 @@ impl ObjectHeader { medium: &mut M, state: ObjectState, ) -> Result<(), StorageError> { - debug_assert!(!state.is_free()); - log::trace!("ObjectHeader::update_state({:?}, {state:?})", self.location); if state == self.state.into() { @@ -381,8 +383,9 @@ impl ObjectHeader { .delete(medium, self.location, object_type) .await? } - ObjectState::Allocated => return Err(StorageError::InvalidOperation), - ObjectState::Free => unreachable!(), + ObjectState::Free | ObjectState::Corrupted | ObjectState::Allocated => { + return Err(StorageError::InvalidOperation); + } }; Ok(())