fat32: move cluster chain cache to FileNode
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user