os/fs/ext4/
adpaters.rs

1//! BlockDevice 适配器:BlockDriver → ext4_rs BlockDevice
2//!
3//! 负责在 Ext4 文件系统块大小 (4096 字节) 和 VirtIO 块设备扇区大小 (512 字节) 之间转换
4
5use crate::config::VIRTIO_BLK_SECTOR_SIZE;
6use crate::device::block::BlockDriver;
7use alloc::sync::Arc;
8use alloc::vec::Vec;
9
10pub struct BlockDeviceAdapter {
11    inner: Arc<dyn BlockDriver>,
12    /// Ext4 文件系统块大小 (通常是 4096)
13    block_size: usize,
14    /// 底层设备扇区大小 (VirtIO 使用 512)
15    sector_size: usize,
16}
17
18impl BlockDeviceAdapter {
19    pub fn new(device: Arc<dyn BlockDriver>, block_size: usize) -> Self {
20        let sector_size = VIRTIO_BLK_SECTOR_SIZE;
21        crate::pr_info!(
22            "[Ext4Adapter] Created adapter: ext4_block_size={}, sector_size={}",
23            block_size,
24            sector_size
25        );
26
27        // 确保块大小是扇区大小的整数倍
28        assert!(
29            block_size % sector_size == 0,
30            "Block size must be a multiple of sector size"
31        );
32
33        Self {
34            inner: device,
35            block_size,
36            sector_size,
37        }
38    }
39}
40
41impl ext4_rs::BlockDevice for BlockDeviceAdapter {
42    fn read_offset(&self, offset: usize) -> Vec<u8> {
43        // ext4_rs 期望读取从 offset 开始的 block_size 字节数据
44        // 我们需要将这个请求转换为多个扇区读取
45
46        // 计算起始扇区和扇区内偏移
47        let start_sector = offset / self.sector_size;
48        let sector_offset = offset % self.sector_size;
49
50        // 计算需要读取多少个扇区才能获得 block_size 字节的数据
51        let bytes_needed = self.block_size;
52        let sectors_needed =
53            (sector_offset + bytes_needed + self.sector_size - 1) / self.sector_size;
54
55        // 读取所有需要的扇区
56        let mut buffer = alloc::vec![0u8; sectors_needed * self.sector_size];
57        for i in 0..sectors_needed {
58            let sector_id = start_sector + i;
59            let buf_offset = i * self.sector_size;
60            let sector_buf = &mut buffer[buf_offset..buf_offset + self.sector_size];
61
62            if !self.inner.read_block(sector_id, sector_buf) {
63                crate::pr_err!(
64                    "[Ext4Adapter] Read error at sector {} (offset {})",
65                    sector_id,
66                    offset
67                );
68                return alloc::vec![0u8; self.block_size];
69            }
70        }
71
72        // 从读取的数据中提取所需的 block_size 字节
73        buffer[sector_offset..sector_offset + self.block_size].to_vec()
74    }
75
76    fn write_offset(&self, offset: usize, data: &[u8]) {
77        // ext4_rs 期望将 data 写入从 offset 开始的位置
78        // data 的长度通常等于 block_size
79
80        // 计算起始扇区和扇区内偏移
81        let start_sector = offset / self.sector_size;
82        let sector_offset = offset % self.sector_size;
83
84        // 计算需要写入多少个扇区
85        let bytes_to_write = data.len();
86        let sectors_needed =
87            (sector_offset + bytes_to_write + self.sector_size - 1) / self.sector_size;
88
89        // 读取-修改-写入
90        let mut buffer = alloc::vec![0u8; sectors_needed * self.sector_size];
91
92        // 1. 读取所有受影响的扇区
93        for i in 0..sectors_needed {
94            let sector_id = start_sector + i;
95            let buf_offset = i * self.sector_size;
96            let sector_buf = &mut buffer[buf_offset..buf_offset + self.sector_size];
97
98            if !self.inner.read_block(sector_id, sector_buf) {
99                crate::pr_err!(
100                    "[Ext4Adapter] Read error at sector {} (for write, offset {})",
101                    sector_id,
102                    offset
103                );
104                return;
105            }
106        }
107
108        // 2. 修改缓冲区
109        buffer[sector_offset..sector_offset + bytes_to_write].copy_from_slice(data);
110
111        // 3. 写回所有扇区
112        for i in 0..sectors_needed {
113            let sector_id = start_sector + i;
114            let buf_offset = i * self.sector_size;
115            let sector_data = &buffer[buf_offset..buf_offset + self.sector_size];
116
117            if !self.inner.write_block(sector_id, sector_data) {
118                crate::pr_err!(
119                    "[Ext4Adapter] Write error at sector {} (offset {})",
120                    sector_id,
121                    offset
122                );
123            }
124        }
125    }
126}