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_upper = (size >> 32) as u32;
|
||||||
self.size_lower = size as u32;
|
self.size_lower = size as u32;
|
||||||
} else {
|
} else {
|
||||||
|
// Unreachable: size is checked in resize()
|
||||||
if size > u32::MAX as u64 {
|
if size > u32::MAX as u64 {
|
||||||
todo!("File too large")
|
todo!("File too large")
|
||||||
}
|
}
|
||||||
@ -242,8 +243,10 @@ impl Inode {
|
|||||||
if size == self.size(fs) {
|
if size == self.size(fs) {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
if size > fs.max_file_size {
|
||||||
// TODO check max inode size
|
// TODO FileTooBig or something
|
||||||
|
return Err(Error::InvalidArgument);
|
||||||
|
}
|
||||||
|
|
||||||
let is_symlink = self
|
let is_symlink = self
|
||||||
.mode
|
.mode
|
||||||
@ -256,11 +259,12 @@ impl Inode {
|
|||||||
} else {
|
} else {
|
||||||
size.div_ceil(fs.block_size as u64)
|
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
|
0
|
||||||
} else {
|
} 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
|
if new_blocks as usize
|
||||||
@ -268,7 +272,7 @@ impl Inode {
|
|||||||
+ fs.pointers_per_block
|
+ fs.pointers_per_block
|
||||||
+ fs.pointers_per_block * 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);
|
return Err(Error::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use core::mem;
|
|||||||
use alloc::{boxed::Box, sync::Arc};
|
use alloc::{boxed::Box, sync::Arc};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bytemuck::Zeroable;
|
use bytemuck::Zeroable;
|
||||||
use data::{FsReadonlyFeatures, FsRequiredFeatures};
|
use data::{FsReadonlyFeatures, FsRequiredFeatures, DIRECT_BLOCK_COUNT};
|
||||||
use dir::DirectoryNode;
|
use dir::DirectoryNode;
|
||||||
use file::RegularNode;
|
use file::RegularNode;
|
||||||
use inode::{InodeAccess, InodeCache};
|
use inode::{InodeAccess, InodeCache};
|
||||||
@ -56,6 +56,8 @@ pub struct Ext2Fs {
|
|||||||
inodes_per_block: usize,
|
inodes_per_block: usize,
|
||||||
pointers_per_block: usize,
|
pointers_per_block: usize,
|
||||||
|
|
||||||
|
max_file_size: u64,
|
||||||
|
|
||||||
required_features: FsRequiredFeatures,
|
required_features: FsRequiredFeatures,
|
||||||
write_features: FsReadonlyFeatures,
|
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 {
|
Ok(Self {
|
||||||
block_size,
|
block_size,
|
||||||
inode_size: superblock.inode_size(),
|
inode_size: superblock.inode_size(),
|
||||||
inodes_per_block: block_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_inodes,
|
||||||
total_blocks,
|
total_blocks,
|
||||||
block_group_inode_count,
|
block_group_inode_count,
|
||||||
block_group_block_count,
|
block_group_block_count,
|
||||||
|
|
||||||
|
max_file_size,
|
||||||
|
|
||||||
mapper,
|
mapper,
|
||||||
inode_cache: OneTimeInit::new(),
|
inode_cache: OneTimeInit::new(),
|
||||||
|
|
||||||
@ -393,26 +410,6 @@ impl Ext2Fs {
|
|||||||
self.inode_cache.get().flush().await
|
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> {
|
async fn read_index(&self, block_index: u32, index: usize) -> Result<u32, Error> {
|
||||||
self.with_block(block_index, |block| {
|
self.with_block(block_index, |block| {
|
||||||
let indirect: &[u32] = unsafe {
|
let indirect: &[u32] = unsafe {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user