fat32: move cluster chain cache to FileNode

This commit is contained in:
2025-08-16 09:05:39 +03:00
parent cb4c0bc4b0
commit 0c2ebbf7b3
2 changed files with 20 additions and 34 deletions
+3 -2
View File
@@ -1,9 +1,10 @@
use core::{any::Any, fmt, mem::MaybeUninit};
use alloc::sync::Arc;
use alloc::{sync::Arc, vec};
use libk::{
block,
error::Error,
task::sync::AsyncMutex,
vfs::{
CommonImpl, CreateInfo, DirectoryImpl, DirectoryOpenPosition, Filename, Metadata, Node,
NodeFlags, NodeRef,
@@ -281,10 +282,10 @@ impl DirectoryNode {
} else {
let file = FileNode {
fs: self.fs.clone(),
cluster,
size_bytes: size,
parent: Some(self.cluster),
metadata,
cluster_chain_cache: AsyncMutex::new(vec![cluster]),
};
Ok(Node::regular(
+17 -32
View File
@@ -1,6 +1,6 @@
use core::any::Any;
use alloc::{sync::Arc, vec, vec::Vec};
use alloc::{sync::Arc, vec::Vec};
use libk::{
block,
error::Error,
@@ -13,28 +13,22 @@ use crate::{data::ClusterNumber, Fat32Fs};
pub struct FileNode {
pub(crate) fs: Arc<Fat32Fs>,
pub(crate) cluster: ClusterNumber,
pub(crate) size_bytes: u32,
pub(crate) metadata: Metadata,
// Will be used when metadata needs to be updated
#[allow(unused)]
pub(crate) parent: Option<ClusterNumber>,
pub(crate) cluster_chain_cache: AsyncMutex<Vec<ClusterNumber>>,
}
// TODO use a "sliding window" to minimize memory usage when working with large files?
struct OpenedFile {
cluster_chain: AsyncMutex<Vec<ClusterNumber>>,
}
impl OpenedFile {
fn new(first_cluster: ClusterNumber) -> Self {
Self {
cluster_chain: AsyncMutex::new(vec![first_cluster]),
}
}
async fn seek(&self, file: &FileNode, cluster_index: usize) -> Result<ClusterNumber, Error> {
let mut chain = self.cluster_chain.lock().await;
impl FileNode {
async fn fetch_cluster_number(
&self,
file: &FileNode,
cluster_index: usize,
) -> Result<ClusterNumber, Error> {
let mut chain = self.cluster_chain_cache.lock().await;
if cluster_index >= chain.len() {
let last = *chain.last().unwrap();
file.fs
@@ -47,15 +41,8 @@ impl OpenedFile {
Ok(chain[cluster_index])
}
}
impl FileNode {
async fn read_inner(
&self,
instance: &OpenedFile,
mut pos: u64,
buffer: &mut [u8],
) -> Result<usize, Error> {
async fn read_inner(&self, mut pos: u64, buffer: &mut [u8]) -> Result<usize, Error> {
if pos >= self.size_bytes as u64 {
return Ok(0);
}
@@ -73,7 +60,9 @@ impl FileNode {
let offset_in_sector = (pos % bps) as usize;
let amount = rem.min(bps as usize - offset_in_sector);
let cluster = instance.seek(self, cluster_index as usize).await?;
let cluster = self
.fetch_cluster_number(self, cluster_index as usize)
.await?;
self.fs
.with_cluster_sector(cluster, sector_in_cluster, |data| {
@@ -119,8 +108,7 @@ impl RegularImpl for FileNode {
if opts.contains_any(OpenOptions::TRUNCATE | OpenOptions::APPEND | OpenOptions::WRITE) {
return Err(Error::ReadOnly);
}
let instance = Arc::new(OpenedFile::new(self.cluster));
Ok((0, Some(instance)))
Ok((0, None))
}
fn close(&self, _node: &NodeRef, _instance: Option<&InstanceData>) -> Result<(), Error> {
@@ -130,14 +118,11 @@ impl RegularImpl for FileNode {
fn read(
&self,
_node: &NodeRef,
instance: Option<&InstanceData>,
_instance: Option<&InstanceData>,
pos: u64,
buf: &mut [u8],
) -> Result<usize, Error> {
let instance = instance
.and_then(|p| p.downcast_ref::<OpenedFile>())
.ok_or(Error::InvalidFile)?;
block!(self.read_inner(instance, pos, buf).await)?
block!(self.read_inner(pos, buf).await)?
}
fn write(