Skip to content

Commit dc3c4d8

Browse files
ext2: fix inode table offset calculation
Signed-off-by: Andy-Python-Programmer <andypythonappdeveloper@gmail.com>
1 parent 21c13c0 commit dc3c4d8

File tree

5 files changed

+72
-25
lines changed

5 files changed

+72
-25
lines changed

src/aero_kernel/src/drivers/block/ide/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl IdeDrive {
5252
}
5353

5454
impl BlockDeviceInterface for IdeDrive {
55-
fn read(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
55+
fn read_block(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
5656
let count = dest.len().ceil_div(512);
5757
let request = Arc::new(DmaRequest::new(sector, count));
5858

@@ -66,7 +66,11 @@ impl BlockDeviceInterface for IdeDrive {
6666
res
6767
}
6868

69-
fn write(&self, _sector: usize, _buf: &[u8]) -> Option<usize> {
69+
fn block_size(&self) -> usize {
70+
todo!()
71+
}
72+
73+
fn write_block(&self, _sector: usize, _buf: &[u8]) -> Option<usize> {
7074
unimplemented!()
7175
}
7276
}

src/aero_kernel/src/drivers/block/nvme/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,12 +468,16 @@ impl<'a> Controller<'a> {
468468
}
469469

470470
impl<'a> BlockDeviceInterface for Controller<'a> {
471-
fn read(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
471+
fn read_block(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
472472
self.namespaces.lock()[0].read(sector, dest);
473473
Some(dest.len())
474474
}
475475

476-
fn write(&self, _sector: usize, _buf: &[u8]) -> Option<usize> {
476+
fn block_size(&self) -> usize {
477+
self.namespaces.lock()[0].block_size
478+
}
479+
480+
fn write_block(&self, _sector: usize, _buf: &[u8]) -> Option<usize> {
477481
unimplemented!()
478482
}
479483
}

src/aero_kernel/src/fs/block/gpt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ impl Gpt {
127127

128128
controller
129129
.device()
130-
.read(1, header.as_bytes_mut())
130+
.read_block(1, header.as_bytes_mut())
131131
.expect("gpt: failed to read first sector");
132132

133133
// SAFETY: The buffer is initialized above.
@@ -144,7 +144,7 @@ impl Gpt {
144144

145145
controller
146146
.device()
147-
.read(
147+
.read_block(
148148
header.starting_lba as _,
149149
MaybeUninit::slice_as_bytes_mut(&mut entry_list),
150150
)

src/aero_kernel/src/fs/block/mod.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
mod gpt;
2121

22+
use alloc::boxed::Box;
2223
use gpt::Gpt;
2324

2425
use core::mem::MaybeUninit;
@@ -31,14 +32,34 @@ use crate::fs::devfs::install_device;
3132
use crate::fs::{Path, Result, MOUNT_MANAGER};
3233

3334
use crate::fs::ext2::Ext2;
35+
use crate::mem::paging::{align_down, align_up};
3436
use crate::utils::sync::Mutex;
3537

3638
use super::devfs::{alloc_device_marker, Device};
3739
use super::inode::INodeInterface;
3840

3941
pub trait BlockDeviceInterface: Send + Sync {
40-
fn read(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize>;
41-
fn write(&self, sector: usize, buf: &[u8]) -> Option<usize>;
42+
fn block_size(&self) -> usize;
43+
44+
fn read_block(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize>;
45+
fn write_block(&self, sector: usize, buf: &[u8]) -> Option<usize>;
46+
47+
fn read(&self, offset: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
48+
let aligned_offset = align_down(offset as u64, self.block_size() as u64) as usize;
49+
let sector = aligned_offset / self.block_size();
50+
51+
let aligned_size = align_up(dest.len() as u64, self.block_size() as u64) as usize;
52+
let mut buffer = Box::<[u8]>::new_uninit_slice(aligned_size);
53+
54+
self.read_block(sector, MaybeUninit::slice_as_bytes_mut(&mut buffer))?;
55+
// SAFETY: We have initialized the buffer above.
56+
let buffer = unsafe { buffer.assume_init() };
57+
58+
let offset = offset - aligned_offset;
59+
MaybeUninit::write_slice(dest, &buffer[offset..(offset + dest.len())]);
60+
61+
Some(dest.len())
62+
}
4263
}
4364

4465
static BLOCK_DEVS: Mutex<BTreeMap<usize, Arc<BlockDevice>>> = Mutex::new(BTreeMap::new());
@@ -113,20 +134,24 @@ impl PartitionBlockDevice {
113134
}
114135

115136
impl BlockDeviceInterface for PartitionBlockDevice {
116-
fn read(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
137+
fn read_block(&self, sector: usize, dest: &mut [MaybeUninit<u8>]) -> Option<usize> {
117138
if sector >= self.size {
118139
return None;
119140
}
120141

121-
self.device.read(self.offset + sector, dest)
142+
self.device.read_block(self.offset + sector, dest)
143+
}
144+
145+
fn block_size(&self) -> usize {
146+
self.device.block_size()
122147
}
123148

124-
fn write(&self, sector: usize, buf: &[u8]) -> Option<usize> {
149+
fn write_block(&self, sector: usize, buf: &[u8]) -> Option<usize> {
125150
if sector >= self.size {
126151
return None;
127152
}
128153

129-
self.device.write(self.offset + sector, buf)
154+
self.device.write_block(self.offset + sector, buf)
130155
}
131156
}
132157

src/aero_kernel/src/fs/ext2/mod.rs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ use core::mem::MaybeUninit;
2222
use alloc::boxed::Box;
2323
use alloc::sync::{Arc, Weak};
2424

25+
use crate::fs::cache::CachedINode;
2526
use crate::utils::CeilDiv;
2627

2728
use super::block::BlockDevice;
2829

2930
use super::cache;
30-
use super::cache::{CachedINode, DirCacheItem, INodeCacheItem};
31+
use super::cache::{DirCacheItem, INodeCacheItem};
3132

3233
use super::inode::{DirEntry, INodeInterface, Metadata};
3334
use super::FileSystem;
@@ -154,7 +155,7 @@ impl From<FileType> for super::inode::FileType {
154155
}
155156
}
156157

157-
#[repr(C)]
158+
#[repr(C, packed)]
158159
#[derive(Debug, Default, Copy, Clone)]
159160
pub struct DiskINode {
160161
type_and_perm: u16,
@@ -213,24 +214,32 @@ impl INode {
213214
Some(inode)
214215
} else {
215216
let fs = ext2.upgrade()?;
217+
let superblock = &fs.superblock;
218+
219+
// There is one inode table per block group and can be located by
220+
// the `inode_table` offset in the group descriptor. Also there are
221+
// `inodes_per_group` inodes per table.
222+
let ino_per_group = superblock.inodes_per_group as usize;
216223

217-
let inode_block_group = (id - 1) / fs.superblock.inodes_per_group as usize;
218-
let inode_table_idx = (id - 1) % fs.superblock.inodes_per_group as usize;
224+
let ino_block_group = (id - 1) / ino_per_group;
225+
let ino_table_index = (id - 1) % ino_per_group;
219226

220-
let group_descriptor = &fs.bgdt[inode_block_group];
221-
let inode_size = core::mem::size_of::<DiskINode>(); // TODO: the inode size can be different
227+
let group_descriptor = &fs.bgdt[ino_block_group];
222228

223-
let table_offset = group_descriptor.inode_table as usize * fs.superblock.block_size();
224-
let inode_offset = table_offset + (inode_size * inode_table_idx);
229+
let table_offset = group_descriptor.inode_table as usize * superblock.block_size();
225230

226231
let mut inode = Box::<DiskINode>::new_uninit();
227-
fs.block
228-
.device()
229-
.read(inode_offset / 512, inode.as_bytes_mut());
232+
233+
fs.block.device().read(
234+
table_offset + (ino_table_index * core::mem::size_of::<DiskINode>()),
235+
inode.as_bytes_mut(),
236+
)?;
230237

231238
// SAFETY: We have initialized the inode above.
232239
let inode = unsafe { inode.assume_init() };
233240

241+
log::debug!("ino_table_index={ino_table_index:?} inode={inode:?}");
242+
234243
Some(icache.make_item_cached(CachedINode::new(Arc::new(Self {
235244
inode,
236245
id,
@@ -268,7 +277,7 @@ impl Ext2 {
268277

269278
pub fn new(block: Arc<BlockDevice>) -> Option<Arc<Self>> {
270279
let mut superblock = Box::<SuperBlock>::new_uninit();
271-
block.device().read(2, superblock.as_bytes_mut())?;
280+
block.device().read_block(2, superblock.as_bytes_mut())?;
272281

273282
// SAFETY: We have initialized the superblock above.
274283
let superblock = unsafe { superblock.assume_init() };
@@ -277,10 +286,15 @@ impl Ext2 {
277286
return None;
278287
}
279288

289+
assert_eq!(
290+
superblock.inode_size as usize,
291+
core::mem::size_of::<DiskINode>()
292+
);
293+
280294
let bgdt_len = superblock.bgdt_len();
281295
let mut bgdt = Box::<[GroupDescriptor]>::new_uninit_slice(bgdt_len);
282296

283-
block.device().read(
297+
block.device().read_block(
284298
superblock.bgdt_sector(),
285299
MaybeUninit::slice_as_bytes_mut(&mut bgdt),
286300
)?;

0 commit comments

Comments
 (0)