os/vfs/impls/
blk_dev_file.rs

1//! 块设备文件的 File trait 实现
2
3use crate::device::BLK_DRIVERS;
4use crate::sync::SpinLock;
5use crate::vfs::devno::get_blkdev_index;
6use crate::vfs::{Dentry, File, FsError, Inode, InodeMetadata, OpenFlags, SeekWhence};
7use alloc::sync::Arc;
8
9/// 块设备文件
10pub struct BlockDeviceFile {
11    /// 关联的 dentry
12    pub dentry: Arc<Dentry>,
13
14    /// 关联的 inode
15    pub inode: Arc<dyn Inode>,
16
17    /// 设备号
18    dev: u64,
19
20    /// 块设备驱动索引(在 BLK_DRIVERS 中)
21    blk_index: Option<usize>,
22
23    /// 打开标志位
24    pub flags: OpenFlags,
25
26    /// 当前偏移量(字节)
27    offset: SpinLock<usize>,
28}
29
30impl BlockDeviceFile {
31    /// 创建新的块设备文件
32    pub fn new(dentry: Arc<Dentry>, flags: OpenFlags) -> Result<Self, FsError> {
33        let inode = dentry.inode.clone();
34        let metadata = inode.metadata()?;
35        let dev = metadata.rdev;
36
37        // 查找块设备驱动
38        let blk_index = get_blkdev_index(dev);
39
40        if blk_index.is_none() {
41            return Err(FsError::NoDevice);
42        }
43
44        Ok(Self {
45            dentry,
46            inode,
47            dev,
48            blk_index,
49            flags,
50            offset: SpinLock::new(0),
51        })
52    }
53
54    /// 获取块大小(通常为 512 字节)
55    const BLOCK_SIZE: usize = 512;
56}
57
58impl File for BlockDeviceFile {
59    fn readable(&self) -> bool {
60        self.flags.readable()
61    }
62
63    fn writable(&self) -> bool {
64        self.flags.writable()
65    }
66
67    fn read(&self, buf: &mut [u8]) -> Result<usize, FsError> {
68        if !self.readable() {
69            return Err(FsError::PermissionDenied);
70        }
71
72        let blk_idx = self.blk_index.ok_or(FsError::NoDevice)?;
73        let drivers = BLK_DRIVERS.read();
74        let driver = drivers.get(blk_idx).ok_or(FsError::NoDevice)?;
75
76        let mut offset_guard = self.offset.lock();
77        let current_offset = *offset_guard;
78
79        // 计算起始扇区和扇区内偏移
80        let start_sector = current_offset / Self::BLOCK_SIZE;
81        let sector_offset = current_offset % Self::BLOCK_SIZE;
82
83        let mut total_read = 0;
84        let mut remaining = buf.len();
85
86        // 读取数据(可能跨多个扇区)
87        while remaining > 0 {
88            let sector_idx = start_sector + total_read / Self::BLOCK_SIZE;
89            let offset_in_sector = if total_read == 0 { sector_offset } else { 0 };
90            let to_read = remaining.min(Self::BLOCK_SIZE - offset_in_sector);
91
92            // 读取一个扇区
93            let mut sector_buf = [0u8; 512];
94            if !driver.read_block(sector_idx, &mut sector_buf) {
95                return Err(FsError::IoError);
96            }
97
98            // 复制数据
99            buf[total_read..total_read + to_read]
100                .copy_from_slice(&sector_buf[offset_in_sector..offset_in_sector + to_read]);
101
102            total_read += to_read;
103            remaining -= to_read;
104        }
105
106        *offset_guard = current_offset + total_read;
107        Ok(total_read)
108    }
109
110    fn write(&self, buf: &[u8]) -> Result<usize, FsError> {
111        if !self.writable() {
112            return Err(FsError::PermissionDenied);
113        }
114
115        let blk_idx = self.blk_index.ok_or(FsError::NoDevice)?;
116        let drivers = BLK_DRIVERS.read();
117        let driver = drivers.get(blk_idx).ok_or(FsError::NoDevice)?;
118
119        let mut offset_guard = self.offset.lock();
120        let current_offset = *offset_guard;
121
122        let start_sector = current_offset / Self::BLOCK_SIZE;
123        let sector_offset = current_offset % Self::BLOCK_SIZE;
124
125        let mut total_written = 0;
126        let mut remaining = buf.len();
127
128        while remaining > 0 {
129            let sector_idx = start_sector + total_written / Self::BLOCK_SIZE;
130            let offset_in_sector = if total_written == 0 { sector_offset } else { 0 };
131            let to_write = remaining.min(Self::BLOCK_SIZE - offset_in_sector);
132
133            let mut sector_buf = [0u8; 512];
134
135            // 如果不是完整扇区写入,需要先读取
136            if offset_in_sector != 0 || to_write != Self::BLOCK_SIZE {
137                if !driver.read_block(sector_idx, &mut sector_buf) {
138                    return Err(FsError::IoError);
139                }
140            }
141
142            // 修改数据
143            sector_buf[offset_in_sector..offset_in_sector + to_write]
144                .copy_from_slice(&buf[total_written..total_written + to_write]);
145
146            // 写回
147            if !driver.write_block(sector_idx, &sector_buf) {
148                return Err(FsError::IoError);
149            }
150
151            total_written += to_write;
152            remaining -= to_write;
153        }
154
155        *offset_guard = current_offset + total_written;
156        Ok(total_written)
157    }
158
159    fn metadata(&self) -> Result<InodeMetadata, FsError> {
160        self.inode.metadata()
161    }
162
163    fn lseek(&self, offset: isize, whence: SeekWhence) -> Result<usize, FsError> {
164        let blk_idx = self.blk_index.ok_or(FsError::NoDevice)?;
165        let drivers = BLK_DRIVERS.read();
166        let driver = drivers.get(blk_idx).ok_or(FsError::NoDevice)?;
167
168        let device_size = driver.total_blocks() * Self::BLOCK_SIZE;
169
170        let mut offset_guard = self.offset.lock();
171        let current = *offset_guard as isize;
172
173        let new_offset = match whence {
174            SeekWhence::Set => offset,
175            SeekWhence::Cur => current + offset,
176            SeekWhence::End => device_size as isize + offset,
177        };
178
179        if new_offset < 0 {
180            return Err(FsError::InvalidArgument);
181        }
182
183        *offset_guard = new_offset as usize;
184        Ok(new_offset as usize)
185    }
186
187    fn offset(&self) -> usize {
188        *self.offset.lock()
189    }
190
191    fn flags(&self) -> OpenFlags {
192        self.flags.clone()
193    }
194
195    fn inode(&self) -> Result<Arc<dyn Inode>, FsError> {
196        Ok(self.inode.clone())
197    }
198
199    fn dentry(&self) -> Result<Arc<Dentry>, FsError> {
200        Ok(self.dentry.clone())
201    }
202    fn as_any(&self) -> &dyn core::any::Any {
203        self
204    }
205}