os/vfs/impls/
blk_dev_file.rs1use 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
9pub struct BlockDeviceFile {
11 pub dentry: Arc<Dentry>,
13
14 pub inode: Arc<dyn Inode>,
16
17 dev: u64,
19
20 blk_index: Option<usize>,
22
23 pub flags: OpenFlags,
25
26 offset: SpinLock<usize>,
28}
29
30impl BlockDeviceFile {
31 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 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 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 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 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 let mut sector_buf = [0u8; 512];
94 if !driver.read_block(sector_idx, &mut sector_buf) {
95 return Err(FsError::IoError);
96 }
97
98 buf[total_read..total_read + to_read]
100 .copy_from_slice(§or_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 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 sector_buf[offset_in_sector..offset_in_sector + to_write]
144 .copy_from_slice(&buf[total_written..total_written + to_write]);
145
146 if !driver.write_block(sector_idx, §or_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}