Skip to content

Commit

Permalink
Add filesystem migration syscall
Browse files Browse the repository at this point in the history
  • Loading branch information
sosthene-nitrokey committed Feb 16, 2024
1 parent 6e70fc4 commit 0c17b42
Showing 1 changed file with 80 additions and 0 deletions.
80 changes: 80 additions & 0 deletions src/manage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use littlefs2::{
fs::DirEntry,
object_safe::DynFilesystem,
path,
path::{Path, PathBuf},
};
Expand All @@ -14,6 +15,17 @@ use trussed::{
Error,
};

#[derive(Debug)]
pub struct Migrator {
/// The function performing the migration
///
/// First argument is the Internal Filesystem, second argument is the External
pub migrate: fn(&dyn DynFilesystem, &dyn DynFilesystem) -> Result<(), littlefs2::io::Error>,

/// The version of the storage for which the migration needs to be run
pub version: u32,
}

use crate::StagingBackend;

pub struct ManageExtension;
Expand All @@ -32,11 +44,21 @@ pub struct FactoryResetClientRequest {
pub client: PathBuf,
}

/// Request a migration of the filesystem
#[derive(Debug, Deserialize, Serialize, Copy, Clone)]
pub struct MigrateRequest {
/// Run migrators where [`version`](Mirgator::version) is larger than `from_version`
pub from_version: u32,
/// Run migrators where [`version`](Mirgator::version) is lower or equal to `to_version`
pub to_version: u32,
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Deserialize, Serialize, Clone)]
pub enum ManageRequest {
FactoryResetDevice(FactoryResetDeviceRequest),
FactoryResetClient(FactoryResetClientRequest),
Migrate(MigrateRequest),
}

impl From<FactoryResetClientRequest> for ManageRequest {
Expand Down Expand Up @@ -71,6 +93,22 @@ impl TryFrom<ManageRequest> for FactoryResetDeviceRequest {
}
}

impl From<MigrateRequest> for ManageRequest {
fn from(value: MigrateRequest) -> Self {
Self::Migrate(value)
}
}

impl TryFrom<ManageRequest> for MigrateRequest {
type Error = Error;
fn try_from(value: ManageRequest) -> Result<Self, Self::Error> {
match value {
ManageRequest::Migrate(v) => Ok(v),
_ => Err(Error::InternalError),
}
}
}

/// Factory reset the entire device
///
/// This will reset all filesystems
Expand All @@ -83,10 +121,15 @@ pub struct FactoryResetDeviceReply;
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct FactoryResetClientReply;

/// Request a migration of the filesystem
#[derive(Debug, Deserialize, Serialize, Copy, Clone)]
pub struct MigrateReply;

#[derive(Debug, Deserialize, Serialize, Clone)]
pub enum ManageReply {
FactoryResetDevice(FactoryResetDeviceReply),
FactoryResetClient(FactoryResetClientReply),
Migrate(MigrateReply),
}

impl From<FactoryResetClientReply> for ManageReply {
Expand Down Expand Up @@ -121,6 +164,22 @@ impl TryFrom<ManageReply> for FactoryResetDeviceReply {
}
}

impl From<MigrateReply> for ManageReply {
fn from(value: MigrateReply) -> Self {
Self::Migrate(value)
}
}

impl TryFrom<ManageReply> for MigrateReply {
type Error = Error;
fn try_from(value: ManageReply) -> Result<Self, Self::Error> {
match value {
ManageReply::Migrate(v) => Ok(v),
_ => Err(Error::InternalError),
}
}
}

impl Extension for ManageExtension {
type Request = ManageRequest;
type Reply = ManageReply;
Expand Down Expand Up @@ -163,12 +222,15 @@ pub struct State {
/// }
/// ```
pub should_preserve_file: fn(&Path, location: Location) -> bool,

pub migrators: &'static [Migrator],
}

impl Default for State {
fn default() -> State {
State {
should_preserve_file: |_, _| false,
migrators: &[],
}
}
}
Expand Down Expand Up @@ -233,6 +295,24 @@ impl ExtensionImpl<ManageExtension> for StagingBackend {
}
Ok(ManageReply::FactoryResetClient(FactoryResetClientReply))
}
ManageRequest::Migrate(MigrateRequest {
from_version,
to_version,
}) => {
let platform = resources.platform();
let store = platform.store();
let internal = store.ifs();
let external = store.efs();
for migration in self.manage.migrators {
if migration.version > *from_version && migration.version <= *to_version {
(migration.migrate)(&**internal, &**external).map_err(|_err| {
error_now!("Migration failed: {_err:?}");
Error::FilesystemWriteFailure
})?;
}
}
Ok(ManageReply::Migrate(MigrateReply))
}
}
}
}

0 comments on commit 0c17b42

Please sign in to comment.