Speed up allocation by tracking last allocated cluster
This commit is contained in:
parent
1ecc9293a2
commit
9129816893
36
src/fs.rs
36
src/fs.rs
@ -205,10 +205,11 @@ impl Default for BootRecord {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone)]
|
||||||
struct FsInfoSector {
|
struct FsInfoSector {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
free_cluster_count: u32,
|
free_cluster_count: Option<u32>,
|
||||||
next_free_cluster: u32,
|
next_free_cluster: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FsInfoSector {
|
impl FsInfoSector {
|
||||||
@ -227,8 +228,14 @@ impl FsInfoSector {
|
|||||||
if struc_sig != Self::STRUC_SIG {
|
if struc_sig != Self::STRUC_SIG {
|
||||||
return Err(Error::new(ErrorKind::Other, "invalid struc_sig in FsInfo sector"));
|
return Err(Error::new(ErrorKind::Other, "invalid struc_sig in FsInfo sector"));
|
||||||
}
|
}
|
||||||
let free_cluster_count = rdr.read_u32::<LittleEndian>()?;
|
let free_cluster_count = match rdr.read_u32::<LittleEndian>()? {
|
||||||
let next_free_cluster = rdr.read_u32::<LittleEndian>()?;
|
0xFFFFFFFF => None,
|
||||||
|
n => Some(n),
|
||||||
|
};
|
||||||
|
let next_free_cluster = match rdr.read_u32::<LittleEndian>()? {
|
||||||
|
0xFFFFFFFF => None,
|
||||||
|
n => Some(n),
|
||||||
|
};
|
||||||
let mut reserved2 = [0u8; 12];
|
let mut reserved2 = [0u8; 12];
|
||||||
rdr.read_exact(&mut reserved2)?;
|
rdr.read_exact(&mut reserved2)?;
|
||||||
let trail_sig = rdr.read_u32::<LittleEndian>()?;
|
let trail_sig = rdr.read_u32::<LittleEndian>()?;
|
||||||
@ -247,8 +254,8 @@ impl FsInfoSector {
|
|||||||
let reserved = [0u8; 480];
|
let reserved = [0u8; 480];
|
||||||
wrt.write(&reserved)?;
|
wrt.write(&reserved)?;
|
||||||
wrt.write_u32::<LittleEndian>(Self::STRUC_SIG)?;
|
wrt.write_u32::<LittleEndian>(Self::STRUC_SIG)?;
|
||||||
wrt.write_u32::<LittleEndian>(self.free_cluster_count)?;
|
wrt.write_u32::<LittleEndian>(self.free_cluster_count.unwrap_or(0xFFFFFFFF))?;
|
||||||
wrt.write_u32::<LittleEndian>(self.next_free_cluster)?;
|
wrt.write_u32::<LittleEndian>(self.next_free_cluster.unwrap_or(0xFFFFFFFF))?;
|
||||||
let reserved2 = [0u8; 12];
|
let reserved2 = [0u8; 12];
|
||||||
wrt.write(&reserved2)?;
|
wrt.write(&reserved2)?;
|
||||||
wrt.write_u32::<LittleEndian>(Self::TRAIL_SIG)?;
|
wrt.write_u32::<LittleEndian>(Self::TRAIL_SIG)?;
|
||||||
@ -287,7 +294,7 @@ pub struct FileSystem<'a> {
|
|||||||
first_data_sector: u32,
|
first_data_sector: u32,
|
||||||
root_dir_sectors: u32,
|
root_dir_sectors: u32,
|
||||||
total_clusters: u32,
|
total_clusters: u32,
|
||||||
fs_info: Option<FsInfoSector>,
|
fs_info: RefCell<FsInfoSector>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> FileSystem<'a> {
|
impl <'a> FileSystem<'a> {
|
||||||
@ -327,9 +334,9 @@ impl <'a> FileSystem<'a> {
|
|||||||
|
|
||||||
let fs_info = if fat_type == FatType::Fat32 {
|
let fs_info = if fat_type == FatType::Fat32 {
|
||||||
disk.seek(SeekFrom::Start(bpb.fs_info_sector as u64 * 512))?;
|
disk.seek(SeekFrom::Start(bpb.fs_info_sector as u64 * 512))?;
|
||||||
Some(FsInfoSector::deserialize(disk)?)
|
FsInfoSector::deserialize(disk)?
|
||||||
} else {
|
} else {
|
||||||
None
|
FsInfoSector::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(FileSystem {
|
Ok(FileSystem {
|
||||||
@ -340,7 +347,7 @@ impl <'a> FileSystem<'a> {
|
|||||||
first_data_sector,
|
first_data_sector,
|
||||||
root_dir_sectors,
|
root_dir_sectors,
|
||||||
total_clusters,
|
total_clusters,
|
||||||
fs_info,
|
fs_info: RefCell::new(fs_info),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,12 +423,11 @@ impl <'a> FileSystem<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn alloc_cluster(&self, prev_cluster: Option<u32>) -> io::Result<u32> {
|
pub(crate) fn alloc_cluster(&self, prev_cluster: Option<u32>) -> io::Result<u32> {
|
||||||
let hint = match self.fs_info {
|
let hint = self.fs_info.borrow().next_free_cluster;
|
||||||
Some(ref info) => Some(info.next_free_cluster),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
let mut fat = self.fat_slice();
|
let mut fat = self.fat_slice();
|
||||||
alloc_cluster(&mut fat, self.fat_type, prev_cluster, hint, self.total_clusters)
|
let cluster = alloc_cluster(&mut fat, self.fat_type, prev_cluster, hint, self.total_clusters)?;
|
||||||
|
self.fs_info.borrow_mut().next_free_cluster = Some(cluster + 1);
|
||||||
|
Ok(cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_status_flags(&self) -> io::Result<FsStatusFlags> {
|
pub fn read_status_flags(&self) -> io::Result<FsStatusFlags> {
|
||||||
|
Loading…
Reference in New Issue
Block a user