Skip to content

Commit 8f95e61

Browse files
authored
fix(fatfs): use Arc for struct FileSystem reference in struct File, struct Dir, etc (#515)
* fix fatfs to use arc Signed-off-by: Koichi Imai <koichi.imai.2@tier4.jp> * fix Signed-off-by: Koichi <koichi.imai.2@tier4.jp> --------- Signed-off-by: Koichi Imai <koichi.imai.2@tier4.jp> Signed-off-by: Koichi <koichi.imai.2@tier4.jp>
1 parent 101f192 commit 8f95e61

4 files changed

Lines changed: 151 additions & 155 deletions

File tree

awkernel_lib/src/file/fatfs/dir.rs

Lines changed: 48 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use alloc::sync::Arc;
12
#[cfg(all(not(feature = "std"), feature = "alloc", feature = "lfn"))]
23
use alloc::vec::Vec;
34
use core::num;
@@ -21,12 +22,12 @@ use super::time::TimeProvider;
2122
#[cfg(feature = "lfn")]
2223
const LFN_PADDING: u16 = 0xFFFF;
2324

24-
pub(crate) enum DirRawStream<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC> {
25-
File(File<'a, IO, TP, OCC>),
26-
Root(DiskSlice<FsIoAdapter<'a, IO, TP, OCC>, FsIoAdapter<'a, IO, TP, OCC>>),
25+
pub(crate) enum DirRawStream<IO: ReadWriteSeek + Send + Sync, TP, OCC> {
26+
File(File<IO, TP, OCC>),
27+
Root(DiskSlice<FsIoAdapter<IO, TP, OCC>, FsIoAdapter<IO, TP, OCC>>),
2728
}
2829

29-
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> DirRawStream<'_, IO, TP, OCC> {
30+
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> DirRawStream<IO, TP, OCC> {
3031
fn abs_pos(&self) -> Option<u64> {
3132
match self {
3233
DirRawStream::File(file) => file.abs_pos(),
@@ -50,7 +51,7 @@ impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> DirRawStream<'_, IO, TP, OCC> {
5051
}
5152

5253
// Note: derive cannot be used because of invalid bounds. See: https://github.com/rust-lang/rust/issues/26925
53-
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> Clone for DirRawStream<'_, IO, TP, OCC> {
54+
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> Clone for DirRawStream<IO, TP, OCC> {
5455
fn clone(&self) -> Self {
5556
match self {
5657
DirRawStream::File(file) => DirRawStream::File(file.clone()),
@@ -59,13 +60,11 @@ impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> Clone for DirRawStream<'_, IO, TP
5960
}
6061
}
6162

62-
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> IoBase for DirRawStream<'_, IO, TP, OCC> {
63+
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> IoBase for DirRawStream<IO, TP, OCC> {
6364
type Error = Error<IO::Error>;
6465
}
6566

66-
impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> Read
67-
for DirRawStream<'_, IO, TP, OCC>
68-
{
67+
impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> Read for DirRawStream<IO, TP, OCC> {
6968
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
7069
match self {
7170
DirRawStream::File(file) => file.read(buf),
@@ -74,9 +73,7 @@ impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> Read
7473
}
7574
}
7675

77-
impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> Write
78-
for DirRawStream<'_, IO, TP, OCC>
79-
{
76+
impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> Write for DirRawStream<IO, TP, OCC> {
8077
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
8178
match self {
8279
DirRawStream::File(file) => file.write(buf),
@@ -91,7 +88,7 @@ impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> Write
9188
}
9289
}
9390

94-
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> Seek for DirRawStream<'_, IO, TP, OCC> {
91+
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> Seek for DirRawStream<IO, TP, OCC> {
9592
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
9693
match self {
9794
DirRawStream::File(file) => file.seek(pos),
@@ -107,45 +104,40 @@ fn split_path(path: &str) -> (&str, Option<&str>) {
107104
})
108105
}
109106

110-
enum DirEntryOrShortName<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC> {
111-
DirEntry(DirEntry<'a, IO, TP, OCC>),
107+
enum DirEntryOrShortName<IO: ReadWriteSeek + Send + Sync, TP, OCC> {
108+
DirEntry(DirEntry<IO, TP, OCC>),
112109
ShortName([u8; SFN_SIZE]),
113110
}
114111

115112
/// A FAT filesystem directory.
116113
///
117114
/// This struct is created by the `open_dir` or `create_dir` methods on `Dir`.
118115
/// The root directory is returned by the `root_dir` method on `FileSystem`.
119-
pub struct Dir<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC> {
120-
stream: DirRawStream<'a, IO, TP, OCC>,
121-
fs: &'a FileSystem<IO, TP, OCC>,
116+
pub struct Dir<IO: ReadWriteSeek + Send + Sync, TP, OCC> {
117+
stream: DirRawStream<IO, TP, OCC>,
118+
fs: Arc<FileSystem<IO, TP, OCC>>,
122119
}
123120

124-
impl<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC> Dir<'a, IO, TP, OCC> {
125-
pub(crate) fn new(
126-
stream: DirRawStream<'a, IO, TP, OCC>,
127-
fs: &'a FileSystem<IO, TP, OCC>,
128-
) -> Self {
121+
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> Dir<IO, TP, OCC> {
122+
pub(crate) fn new(stream: DirRawStream<IO, TP, OCC>, fs: Arc<FileSystem<IO, TP, OCC>>) -> Self {
129123
Dir { stream, fs }
130124
}
131125

132126
/// Creates directory entries iterator.
133127
#[must_use]
134128
#[allow(clippy::iter_not_returning_iterator)]
135-
pub fn iter(&self) -> DirIter<'a, IO, TP, OCC> {
136-
DirIter::new(self.stream.clone(), self.fs, true)
129+
pub fn iter(&self) -> DirIter<IO, TP, OCC> {
130+
DirIter::new(self.stream.clone(), self.fs.clone(), true)
137131
}
138132
}
139133

140-
impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
141-
Dir<'a, IO, TP, OCC>
142-
{
134+
impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter> Dir<IO, TP, OCC> {
143135
fn find_entry(
144136
&self,
145137
name: &str,
146138
is_dir: Option<bool>,
147139
mut short_name_gen: Option<&mut ShortNameGenerator>,
148-
) -> Result<DirEntry<'a, IO, TP, OCC>, Error<IO::Error>> {
140+
) -> Result<DirEntry<IO, TP, OCC>, Error<IO::Error>> {
149141
for r in self.iter() {
150142
let e = r?;
151143
// compare name ignoring case
@@ -172,8 +164,8 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
172164
#[allow(clippy::type_complexity)]
173165
pub(crate) fn find_volume_entry(
174166
&self,
175-
) -> Result<Option<DirEntry<'a, IO, TP, OCC>>, Error<IO::Error>> {
176-
for r in DirIter::new(self.stream.clone(), self.fs, false) {
167+
) -> Result<Option<DirEntry<IO, TP, OCC>>, Error<IO::Error>> {
168+
for r in DirIter::new(self.stream.clone(), self.fs.clone(), false) {
177169
let e = r?;
178170
if e.data.is_volume() {
179171
return Ok(Some(e));
@@ -186,7 +178,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
186178
&self,
187179
name: &str,
188180
is_dir: Option<bool>,
189-
) -> Result<DirEntryOrShortName<'a, IO, TP, OCC>, Error<IO::Error>> {
181+
) -> Result<DirEntryOrShortName<IO, TP, OCC>, Error<IO::Error>> {
190182
let mut short_name_gen = ShortNameGenerator::new(name);
191183
loop {
192184
// find matching entry
@@ -241,7 +233,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
241233
/// * `Error::NotFound` will be returned if `path` points to a non-existing directory entry.
242234
/// * `Error::InvalidInput` will be returned if `path` points to a file that is a directory.
243235
/// * `Error::Io` will be returned if the underlying storage object returned an I/O error.
244-
pub fn open_file(&self, path: &str) -> Result<File<'a, IO, TP, OCC>, Error<IO::Error>> {
236+
pub fn open_file(&self, path: &str) -> Result<File<IO, TP, OCC>, Error<IO::Error>> {
245237
log::trace!("Dir::open_file {path}");
246238
// traverse path
247239
let (name, rest_opt) = split_path(path);
@@ -268,7 +260,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
268260
/// * `Error::UnsupportedFileNameCharacter` will be returned if the file name contains an invalid character.
269261
/// * `Error::NotEnoughSpace` will be returned if there is not enough free space to create a new file.
270262
/// * `Error::Io` will be returned if the underlying storage object returned an I/O error.
271-
pub fn create_file(&self, path: &str) -> Result<File<'a, IO, TP, OCC>, Error<IO::Error>> {
263+
pub fn create_file(&self, path: &str) -> Result<File<IO, TP, OCC>, Error<IO::Error>> {
272264
log::trace!("Dir::create_file {path}");
273265
// traverse path
274266
let (name, rest_opt) = split_path(path);
@@ -321,7 +313,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
321313
// directory does not exist - create it
322314
DirEntryOrShortName::ShortName(short_name) => {
323315
// alloc cluster for directory data
324-
let cluster = self.fs.alloc_cluster(None, true)?;
316+
let cluster = FileSystem::alloc_cluster(&self.fs, None, true)?;
325317
// create entry in parent directory
326318
let sfn_entry =
327319
self.create_sfn_entry(short_name, FileAttributes::DIRECTORY, Some(cluster));
@@ -395,7 +387,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
395387
}
396388
// free data
397389
if let Some(n) = e.first_cluster() {
398-
self.fs.free_cluster_chain(n)?;
390+
FileSystem::free_cluster_chain(&self.fs, n)?;
399391
}
400392
// free long and short name entries
401393
let mut stream = self.stream.clone();
@@ -495,7 +487,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
495487
fn find_free_entries(
496488
&self,
497489
num_entries: u32,
498-
) -> Result<DirRawStream<'a, IO, TP, OCC>, Error<IO::Error>> {
490+
) -> Result<DirRawStream<IO, TP, OCC>, Error<IO::Error>> {
499491
let mut stream = self.stream.clone();
500492
let mut first_free: u32 = 0;
501493
let mut num_free: u32 = 0;
@@ -559,7 +551,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
559551
&self,
560552
lfn_utf16: &LfnBuffer,
561553
short_name: &[u8; SFN_SIZE],
562-
) -> Result<(DirRawStream<'a, IO, TP, OCC>, u64), Error<IO::Error>> {
554+
) -> Result<(DirRawStream<IO, TP, OCC>, u64), Error<IO::Error>> {
563555
// get short name checksum
564556
let lfn_chsum = lfn_checksum(short_name);
565557
// create LFN entries generator
@@ -576,7 +568,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
576568
}
577569

578570
#[allow(clippy::type_complexity)]
579-
fn alloc_sfn_entry(&self) -> Result<(DirRawStream<'a, IO, TP, OCC>, u64), Error<IO::Error>> {
571+
fn alloc_sfn_entry(&self) -> Result<(DirRawStream<IO, TP, OCC>, u64), Error<IO::Error>> {
580572
let mut stream = self.find_free_entries(1)?;
581573
let start_pos = stream.seek(super::super::io::SeekFrom::Current(0))?;
582574
Ok((stream, start_pos))
@@ -586,7 +578,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
586578
&self,
587579
name: &str,
588580
raw_entry: DirFileEntryData,
589-
) -> Result<DirEntry<'a, IO, TP, OCC>, Error<IO::Error>> {
581+
) -> Result<DirEntry<IO, TP, OCC>, Error<IO::Error>> {
590582
log::trace!("Dir::write_entry {name}");
591583
// check if name doesn't contain unsupported characters
592584
validate_long_name(name)?;
@@ -618,7 +610,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
618610
short_name,
619611
#[cfg(feature = "lfn")]
620612
lfn_utf16,
621-
fs: self.fs,
613+
fs: self.fs.clone(),
622614
entry_pos: start_abs_pos,
623615
offset_range: (start_pos, end_pos),
624616
})
@@ -627,30 +619,30 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter>
627619

628620
// Note: derive cannot be used because of invalid bounds. See: https://github.com/rust-lang/rust/issues/26925
629621
impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC: OemCpConverter> Clone
630-
for Dir<'_, IO, TP, OCC>
622+
for Dir<IO, TP, OCC>
631623
{
632624
fn clone(&self) -> Self {
633625
Self {
634626
stream: self.stream.clone(),
635-
fs: self.fs,
627+
fs: self.fs.clone(),
636628
}
637629
}
638630
}
639631

640632
/// An iterator over the directory entries.
641633
///
642634
/// This struct is created by the `iter` method on `Dir`.
643-
pub struct DirIter<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC> {
644-
stream: DirRawStream<'a, IO, TP, OCC>,
645-
fs: &'a FileSystem<IO, TP, OCC>,
635+
pub struct DirIter<IO: ReadWriteSeek + Send + Sync, TP, OCC> {
636+
stream: DirRawStream<IO, TP, OCC>,
637+
fs: Arc<FileSystem<IO, TP, OCC>>,
646638
skip_volume: bool,
647639
err: bool,
648640
}
649641

650-
impl<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC> DirIter<'a, IO, TP, OCC> {
642+
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> DirIter<IO, TP, OCC> {
651643
fn new(
652-
stream: DirRawStream<'a, IO, TP, OCC>,
653-
fs: &'a FileSystem<IO, TP, OCC>,
644+
stream: DirRawStream<IO, TP, OCC>,
645+
fs: Arc<FileSystem<IO, TP, OCC>>,
654646
skip_volume: bool,
655647
) -> Self {
656648
DirIter {
@@ -662,7 +654,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC> DirIter<'a, IO, TP, OCC> {
662654
}
663655
}
664656

665-
impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> DirIter<'a, IO, TP, OCC> {
657+
impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> DirIter<IO, TP, OCC> {
666658
fn should_skip_entry(&self, raw_entry: &DirEntryData) -> bool {
667659
if raw_entry.is_deleted() {
668660
return true;
@@ -674,7 +666,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> DirIter<'a, IO,
674666
}
675667

676668
#[allow(clippy::type_complexity)]
677-
fn read_dir_entry(&mut self) -> Result<Option<DirEntry<'a, IO, TP, OCC>>, Error<IO::Error>> {
669+
fn read_dir_entry(&mut self) -> Result<Option<DirEntry<IO, TP, OCC>>, Error<IO::Error>> {
678670
log::trace!("DirIter::read_dir_entry");
679671
let mut lfn_builder = LongNameBuilder::new();
680672
let mut offset = self.stream.seek(SeekFrom::Current(0))?;
@@ -713,7 +705,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> DirIter<'a, IO,
713705
short_name,
714706
#[cfg(feature = "lfn")]
715707
lfn_utf16: lfn_builder.into_buf(),
716-
fs: self.fs,
708+
fs: self.fs.clone(),
717709
entry_pos: abs_pos,
718710
offset_range: (begin_offset, offset),
719711
}));
@@ -729,21 +721,19 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> DirIter<'a, IO,
729721
}
730722

731723
// Note: derive cannot be used because of invalid bounds. See: https://github.com/rust-lang/rust/issues/26925
732-
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> Clone for DirIter<'_, IO, TP, OCC> {
724+
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> Clone for DirIter<IO, TP, OCC> {
733725
fn clone(&self) -> Self {
734726
Self {
735727
stream: self.stream.clone(),
736-
fs: self.fs,
728+
fs: self.fs.clone(),
737729
err: self.err,
738730
skip_volume: self.skip_volume,
739731
}
740732
}
741733
}
742734

743-
impl<'a, IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> Iterator
744-
for DirIter<'a, IO, TP, OCC>
745-
{
746-
type Item = Result<DirEntry<'a, IO, TP, OCC>, Error<IO::Error>>;
735+
impl<IO: ReadWriteSeek + Send + Sync, TP: TimeProvider, OCC> Iterator for DirIter<IO, TP, OCC> {
736+
type Item = Result<DirEntry<IO, TP, OCC>, Error<IO::Error>>;
747737

748738
fn next(&mut self) -> Option<Self::Item> {
749739
if self.err {

awkernel_lib/src/file/fatfs/dir_entry.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#[cfg(all(not(feature = "std"), feature = "alloc"))]
22
use alloc::string::String;
3+
use alloc::sync::Arc;
34
use bitflags::bitflags;
45
use core::char;
56
use core::convert::TryInto;
@@ -552,18 +553,18 @@ impl DirEntryEditor {
552553
///
553554
/// `DirEntry` is returned by `DirIter` when reading a directory.
554555
#[derive(Clone)]
555-
pub struct DirEntry<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC> {
556+
pub struct DirEntry<IO: ReadWriteSeek + Send + Sync, TP, OCC> {
556557
pub(crate) data: DirFileEntryData,
557558
pub(crate) short_name: ShortName,
558559
#[cfg(feature = "lfn")]
559560
pub(crate) lfn_utf16: LfnBuffer,
560561
pub(crate) entry_pos: u64,
561562
pub(crate) offset_range: (u64, u64),
562-
pub(crate) fs: &'a FileSystem<IO, TP, OCC>,
563+
pub(crate) fs: Arc<FileSystem<IO, TP, OCC>>,
563564
}
564565

565566
#[allow(clippy::len_without_is_empty)]
566-
impl<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC: OemCpConverter> DirEntry<'a, IO, TP, OCC> {
567+
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC: OemCpConverter> DirEntry<IO, TP, OCC> {
567568
/// Returns short file name.
568569
///
569570
/// Non-ASCII characters are replaced by the replacement character (U+FFFD).
@@ -647,9 +648,9 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC: OemCpConverter> DirEntry<'a,
647648
///
648649
/// Will panic if this is not a file.
649650
#[must_use]
650-
pub fn to_file(&self) -> File<'a, IO, TP, OCC> {
651+
pub fn to_file(&self) -> File<IO, TP, OCC> {
651652
assert!(!self.is_dir(), "Not a file entry");
652-
File::new(self.first_cluster(), Some(self.editor()), self.fs)
653+
File::new(self.first_cluster(), Some(self.editor()), self.fs.clone())
653654
}
654655

655656
/// Returns `Dir` struct for this entry.
@@ -658,14 +659,14 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC: OemCpConverter> DirEntry<'a,
658659
///
659660
/// Will panic if this is not a directory.
660661
#[must_use]
661-
pub fn to_dir(&self) -> Dir<'a, IO, TP, OCC> {
662+
pub fn to_dir(&self) -> Dir<IO, TP, OCC> {
662663
assert!(self.is_dir(), "Not a directory entry");
663664
match self.first_cluster() {
664665
Some(n) => {
665-
let file = File::new(Some(n), Some(self.editor()), self.fs);
666-
Dir::new(DirRawStream::File(file), self.fs)
666+
let file = File::new(Some(n), Some(self.editor()), self.fs.clone());
667+
Dir::new(DirRawStream::File(file), self.fs.clone())
667668
}
668-
None => self.fs.root_dir(),
669+
None => FileSystem::root_dir(&self.fs),
669670
}
670671
}
671672

@@ -740,7 +741,7 @@ impl<'a, IO: ReadWriteSeek + Send + Sync, TP, OCC: OemCpConverter> DirEntry<'a,
740741
}
741742
}
742743

743-
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> fmt::Debug for DirEntry<'_, IO, TP, OCC> {
744+
impl<IO: ReadWriteSeek + Send + Sync, TP, OCC> fmt::Debug for DirEntry<IO, TP, OCC> {
744745
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
745746
self.data.fmt(f)
746747
}

0 commit comments

Comments
 (0)