ext2: properly handle max file size
This commit is contained in:
parent
d8f035dc69
commit
a126118589
@ -229,6 +229,7 @@ impl Inode {
|
||||
self.size_upper = (size >> 32) as u32;
|
||||
self.size_lower = size as u32;
|
||||
} else {
|
||||
// Unreachable: size is checked in resize()
|
||||
if size > u32::MAX as u64 {
|
||||
todo!("File too large")
|
||||
}
|
||||
@ -242,8 +243,10 @@ impl Inode {
|
||||
if size == self.size(fs) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
// TODO check max inode size
|
||||
if size > fs.max_file_size {
|
||||
// TODO FileTooBig or something
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
|
||||
let is_symlink = self
|
||||
.mode
|
||||
@ -256,11 +259,12 @@ impl Inode {
|
||||
} else {
|
||||
size.div_ceil(fs.block_size as u64)
|
||||
};
|
||||
// TODO check size_upper as well?
|
||||
let old_blocks = if is_symlink && self.size_lower < 60 {
|
||||
|
||||
let old_size = self.size(fs);
|
||||
let old_blocks = if is_symlink && old_size < 60 {
|
||||
0
|
||||
} else {
|
||||
self.size(fs).div_ceil(fs.block_size as u64)
|
||||
old_size.div_ceil(fs.block_size as u64)
|
||||
};
|
||||
|
||||
if new_blocks as usize
|
||||
@ -268,7 +272,7 @@ impl Inode {
|
||||
+ fs.pointers_per_block
|
||||
+ fs.pointers_per_block * fs.pointers_per_block
|
||||
{
|
||||
log::warn!("ext2: only L0/L1 are supported");
|
||||
log::warn!("ext2: only L0/L1/L2 are supported");
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ use core::mem;
|
||||
use alloc::{boxed::Box, sync::Arc};
|
||||
use async_trait::async_trait;
|
||||
use bytemuck::Zeroable;
|
||||
use data::{FsReadonlyFeatures, FsRequiredFeatures};
|
||||
use data::{FsReadonlyFeatures, FsRequiredFeatures, DIRECT_BLOCK_COUNT};
|
||||
use dir::DirectoryNode;
|
||||
use file::RegularNode;
|
||||
use inode::{InodeAccess, InodeCache};
|
||||
@ -56,6 +56,8 @@ pub struct Ext2Fs {
|
||||
inodes_per_block: usize,
|
||||
pointers_per_block: usize,
|
||||
|
||||
max_file_size: u64,
|
||||
|
||||
required_features: FsRequiredFeatures,
|
||||
write_features: FsReadonlyFeatures,
|
||||
|
||||
@ -259,17 +261,32 @@ impl Ext2Fs {
|
||||
}
|
||||
};
|
||||
|
||||
let pointers_per_block = block_size / size_of::<u32>();
|
||||
let max_inode_blocks = (DIRECT_BLOCK_COUNT
|
||||
+ pointers_per_block
|
||||
+ pointers_per_block * pointers_per_block
|
||||
+ pointers_per_block * pointers_per_block * pointers_per_block)
|
||||
as u64;
|
||||
let max_file_size = max_inode_blocks.saturating_mul(block_size as u64);
|
||||
let max_file_size = if write_features.contains(FsReadonlyFeatures::FILE_SIZE_64_BIT) {
|
||||
max_file_size
|
||||
} else {
|
||||
max_file_size.min(u32::MAX as u64)
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
block_size,
|
||||
inode_size: superblock.inode_size(),
|
||||
inodes_per_block: block_size / superblock.inode_size(),
|
||||
pointers_per_block: block_size / size_of::<u32>(),
|
||||
pointers_per_block,
|
||||
|
||||
total_inodes,
|
||||
total_blocks,
|
||||
block_group_inode_count,
|
||||
block_group_block_count,
|
||||
|
||||
max_file_size,
|
||||
|
||||
mapper,
|
||||
inode_cache: OneTimeInit::new(),
|
||||
|
||||
@ -393,26 +410,6 @@ impl Ext2Fs {
|
||||
self.inode_cache.get().flush().await
|
||||
}
|
||||
|
||||
// pub async fn flush_superblock(&self) -> Result<(), Error> {
|
||||
// let state = self.state.read();
|
||||
// if state.dirty {
|
||||
// log::info!("Flushing superblock");
|
||||
// log::info!(
|
||||
// "inodes {} blocks {}",
|
||||
// state.superblock.total_unallocated_inodes,
|
||||
// state.superblock.total_unallocated_blocks
|
||||
// );
|
||||
// self.mapper
|
||||
// .device()
|
||||
// .write_exact(
|
||||
// data::SUPERBLOCK_OFFSET,
|
||||
// bytemuck::bytes_of(&state.superblock),
|
||||
// )
|
||||
// .await?;
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
async fn read_index(&self, block_index: u32, index: usize) -> Result<u32, Error> {
|
||||
self.with_block(block_index, |block| {
|
||||
let indirect: &[u32] = unsafe {
|
||||
|
Loading…
x
Reference in New Issue
Block a user