Skip to content

Commit

Permalink
Add Filesystem::try_mount
Browse files Browse the repository at this point in the history
When mounting a filesystem, often code like this is used:

    if !Filesystem::is_mountable(alloc, storage) {
        Filesystem::format(storage).ok();
    }
    Filesystem::mount(alloc, storage)

This mounts the filesystem twice because Filesystem::is_mountable is
equivalent to Filesystem::mount(...).is_err().  Depending on the storage
implementation, mounting the filesystem can have significant cost.
But directly calling Filesystem::mount and re-mounting in the error case
is prohibited by the borrow checker.

This patch adds a try_mount method that accepts a callable that is
called on mount error.  Afterwards, mounting is re-tried.
  • Loading branch information
robin-nitrokey committed Apr 24, 2024
1 parent 960e57d commit aef3ff1
Showing 1 changed file with 21 additions and 3 deletions.
24 changes: 21 additions & 3 deletions src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub type Bytes<SIZE> = generic_array::GenericArray<u8, SIZE>;

use crate::{
driver,
io::{self, OpenSeekFrom, Result},
io::{self, Error, OpenSeekFrom, Result},
path,
path::{Path, PathBuf},
};
Expand Down Expand Up @@ -1179,10 +1179,28 @@ impl<'a, Storage: driver::Storage> Filesystem<'a, Storage> {
impl<'a, Storage: driver::Storage> Filesystem<'a, Storage> {
pub fn mount(alloc: &'a mut Allocation<Storage>, storage: &'a mut Storage) -> Result<Self> {
let fs = Self::new(alloc, storage);
let mut alloc = fs.alloc.borrow_mut();
fs.raw_mount()?;
Ok(fs)
}

/// Mount the filesystem or, if that fails, call `f` with the mount error and the storage and then try again.
pub fn try_mount<F>(alloc: &'a mut Allocation<Storage>, storage: &'a mut Storage, f: F) -> Result<Self>
where
F: FnOnce(Error, &mut Storage) -> Result<()>,
{
let fs = Self::new(alloc, storage);
if let Err(err) = fs.raw_mount() {
f(err, fs.storage)?;
fs.raw_mount()?;
}
Ok(fs)
}

fn raw_mount(&self) -> Result<()> {
let mut alloc = self.alloc.borrow_mut();
let return_code = unsafe { ll::lfs_mount(&mut alloc.state, &alloc.config) };
drop(alloc);
io::result_from(fs, return_code)
io::result_from((), return_code)
}

// Not public, user should use `mount`, possibly after `format`
Expand Down

0 comments on commit aef3ff1

Please sign in to comment.