From 3c226765d9ebca5bc8bb00b761a8482486436b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Mon, 16 Jun 2025 12:29:38 +0200 Subject: [PATCH 1/3] Fix the `Allocation` lifetime in `File::open` This also a breaking change because the `unsafe` `open` function did not take the correct lifetime. It think it's an acceptable breaking change because the previous behaviour was buggy and any code that depends on it likely has a use after free. --- src/fs.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/fs.rs b/src/fs.rs index 5bbdaea1..27244bb4 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -1,6 +1,7 @@ //! Experimental Filesystem version using closures. use core::ffi::{c_int, c_void}; +use core::marker::PhantomData; use core::ptr::addr_of; use core::ptr::addr_of_mut; use core::{ @@ -613,6 +614,7 @@ pub struct File<'a, 'b, S: driver::Storage> { // We must store a raw pointer here since the FFI retains a copy of a pointer // to the field alloc.state, so we cannot assert unique mutable access. alloc: RefCell<*mut FileAllocation>, + phantom: PhantomData>>, fs: &'b Filesystem<'a, S>, } @@ -803,7 +805,7 @@ impl OpenOptions { pub unsafe fn open<'a, 'b, S: driver::Storage>( &self, fs: &'b Filesystem<'a, S>, - alloc: &mut FileAllocation, + alloc: &'b mut FileAllocation, path: &Path, ) -> Result> { alloc.config.buffer = alloc.cache.get() as *mut _; @@ -820,6 +822,7 @@ impl OpenOptions { let file = File { alloc: RefCell::new(alloc), + phantom: PhantomData, fs, }; From 9758ff381bdde46ba7af75be5b9fcaa8df0f6ed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Mon, 16 Jun 2025 12:48:05 +0200 Subject: [PATCH 2/3] Make `Filesystem` `Send` `Filesystem` is still `!Sync`, so this allows putting the filesystem behind a `Mutex` and sharing it across threads but still prevents concurrent operations from multiple threads. See https://github.com/trussed-dev/littlefs2/issues/108#issuecomment-2975793283 --- src/fs.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/fs.rs b/src/fs.rs index 27244bb4..c8fc656f 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -73,6 +73,19 @@ pub struct Allocation { state: ll::lfs_t, } +/// # Safety +/// +/// All operations are done on `&mut Allocation, and the reference is held +/// during the entire lifetime of the filesystem, so once the reference is +/// available again, the filesystem is closed +unsafe impl Sync for Allocation {} +/// # Safety +/// +/// All operations are done on `&mut Allocation, and the reference is held +/// during the entire lifetime of the filesystem, so once the reference is +/// available again, the filesystem is closed +unsafe impl Send for Allocation {} + // pub fn check_storage_requirements( impl Default for Allocation { @@ -1547,4 +1560,21 @@ mod tests { }) .unwrap(); } + + #[allow(unreachable_code)] + fn _filesystem_is_sync() { + fn assert_is_sync(_: &T) -> R { + todo!() + } + fn assert_is_send(_: &T) -> R { + todo!() + } + + assert_is_sync::, ()>(todo!()); + assert_is_send::<&mut Allocation, ()>(todo!()); + assert_is_send::>, ()>(todo!()); + + let mut test_storage = TestStorage::new(); + Filesystem::mount_and_then(&mut test_storage, |fs| assert_is_send(fs)).unwrap() + } } From 2c7311e7fb7d6109bd5d7e832959181bc52b1df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Thu, 26 Jun 2025 14:28:56 +0200 Subject: [PATCH 3/3] fixup! Fix the `Allocation` lifetime in `File::open` --- src/fs.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/fs.rs b/src/fs.rs index c8fc656f..f777d1fa 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -1,7 +1,6 @@ //! Experimental Filesystem version using closures. use core::ffi::{c_int, c_void}; -use core::marker::PhantomData; use core::ptr::addr_of; use core::ptr::addr_of_mut; use core::{ @@ -627,7 +626,6 @@ pub struct File<'a, 'b, S: driver::Storage> { // We must store a raw pointer here since the FFI retains a copy of a pointer // to the field alloc.state, so we cannot assert unique mutable access. alloc: RefCell<*mut FileAllocation>, - phantom: PhantomData>>, fs: &'b Filesystem<'a, S>, } @@ -835,7 +833,6 @@ impl OpenOptions { let file = File { alloc: RefCell::new(alloc), - phantom: PhantomData, fs, };