Nothing to see here, move along meow
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 9.2 kB View raw
1#[cfg(feature = "userspace")] 2mod real_io { 3 use crate::error::FsError; 4 use lancer_core::block_io::{BlockRequest, BlockResponse}; 5 use lancer_core::fs::BLOCK_SIZE_MIN; 6 use lancer_core::packet_ring::{PacketRingReader, PacketRingWriter}; 7 use lancer_user::syscall; 8 9 const DRIVER_NOTIF_SLOT: u64 = 4; 10 const NOTIF_SLOT: u64 = 3; 11 const POLL_LIMIT: u32 = 10_000_000; 12 const PUSH_RETRY_LIMIT: u32 = 100_000; 13 14 pub struct BlockIo { 15 request_ring: PacketRingWriter, 16 response_ring: PacketRingReader, 17 data_area: *mut u8, 18 data_area_size: usize, 19 sector_size: u32, 20 next_tag: u32, 21 } 22 23 impl BlockIo { 24 #[allow(clippy::missing_safety_doc)] 25 pub unsafe fn init( 26 request_ring: PacketRingWriter, 27 response_ring: PacketRingReader, 28 data_area: *mut u8, 29 data_area_size: usize, 30 sector_size: u32, 31 ) -> Self { 32 Self { 33 request_ring, 34 response_ring, 35 data_area, 36 data_area_size, 37 sector_size, 38 next_tag: 0, 39 } 40 } 41 42 fn alloc_tag(&mut self) -> u32 { 43 let tag = self.next_tag; 44 self.next_tag = self.next_tag.wrapping_add(1); 45 tag 46 } 47 48 fn push_request(&self, req: &BlockRequest) -> Result<(), FsError> { 49 let data = req.as_bytes(); 50 let pushed = (0..PUSH_RETRY_LIMIT).any(|_| self.request_ring.try_push(data)); 51 match pushed { 52 true => Ok(()), 53 false => Err(FsError::RingFull), 54 } 55 } 56 57 fn wait_response(&self, expected_tag: u32) -> Result<BlockResponse, FsError> { 58 let mut stale_count: u32 = 0; 59 (0..POLL_LIMIT) 60 .find_map(|_| { 61 let mut buf = [0u8; 32]; 62 match self.response_ring.try_pop(&mut buf) { 63 Some(len) if len >= BlockResponse::SIZE => { 64 match BlockResponse::from_bytes(&buf) { 65 Some(resp) if resp.tag == expected_tag => Some(Ok(resp)), 66 Some(_) => { 67 stale_count += 1; 68 match stale_count > 16 { 69 true => Some(Err(FsError::Io(0xFFFD))), 70 false => None, 71 } 72 } 73 None => Some(Err(FsError::Io(0xFFFC))), 74 } 75 } 76 Some(_) => Some(Err(FsError::Io(0xFFFC))), 77 None => { 78 syscall::notify_wait(NOTIF_SLOT); 79 None 80 } 81 } 82 }) 83 .unwrap_or(Err(FsError::Io(0xFFFF))) 84 } 85 86 fn submit_and_wait(&mut self, req: BlockRequest) -> Result<BlockResponse, FsError> { 87 let tag = req.tag; 88 self.push_request(&req)?; 89 syscall::notify_signal(DRIVER_NOTIF_SLOT, 1); 90 self.wait_response(tag) 91 } 92 93 fn blocks_to_lba(&self, block_num: u64) -> u64 { 94 block_num * (BLOCK_SIZE_MIN as u64 / self.sector_size as u64) 95 } 96 97 fn blocks_to_sectors(&self, block_count: u16) -> Result<u16, FsError> { 98 let ratio = BLOCK_SIZE_MIN / self.sector_size; 99 (block_count as u32) 100 .checked_mul(ratio) 101 .and_then(|n| u16::try_from(n).ok()) 102 .ok_or(FsError::InvalidBlock) 103 } 104 105 pub fn read_blocks( 106 &mut self, 107 block_num: u64, 108 count: u16, 109 buf: &mut [u8], 110 ) -> Result<(), FsError> { 111 let sector_count = self.blocks_to_sectors(count)?; 112 let transfer_bytes = sector_count as usize * self.sector_size as usize; 113 let tag = self.alloc_tag(); 114 let lba = self.blocks_to_lba(block_num); 115 let req = BlockRequest::read(tag, lba, sector_count, 0); 116 let resp = self.submit_and_wait(req)?; 117 118 match resp.status { 119 0 => { 120 let copy_len = transfer_bytes.min(buf.len()).min(self.data_area_size); 121 unsafe { 122 core::ptr::copy_nonoverlapping( 123 self.data_area as *const u8, 124 buf.as_mut_ptr(), 125 copy_len, 126 ); 127 } 128 Ok(()) 129 } 130 status => Err(FsError::Io(status)), 131 } 132 } 133 134 pub fn write_blocks( 135 &mut self, 136 block_num: u64, 137 count: u16, 138 buf: &[u8], 139 ) -> Result<(), FsError> { 140 let sector_count = self.blocks_to_sectors(count)?; 141 let transfer_bytes = sector_count as usize * self.sector_size as usize; 142 let copy_len = transfer_bytes.min(buf.len()).min(self.data_area_size); 143 unsafe { 144 core::ptr::copy_nonoverlapping(buf.as_ptr(), self.data_area, copy_len); 145 } 146 147 let tag = self.alloc_tag(); 148 let lba = self.blocks_to_lba(block_num); 149 let req = BlockRequest::write(tag, lba, sector_count, 0); 150 let resp = self.submit_and_wait(req)?; 151 152 match resp.status { 153 0 => Ok(()), 154 status => Err(FsError::Io(status)), 155 } 156 } 157 158 pub fn flush(&mut self) -> Result<(), FsError> { 159 let tag = self.alloc_tag(); 160 let req = BlockRequest::flush(tag); 161 let resp = self.submit_and_wait(req)?; 162 163 match resp.status { 164 0 => Ok(()), 165 status => Err(FsError::Io(status)), 166 } 167 } 168 169 pub fn sector_size(&self) -> u32 { 170 self.sector_size 171 } 172 } 173} 174 175#[cfg(feature = "userspace")] 176pub use real_io::BlockIo; 177 178#[cfg(not(feature = "userspace"))] 179mod mem_io { 180 use crate::error::FsError; 181 182 const BLOCK_SIZE: usize = 4096; 183 184 pub struct BlockIo { 185 storage: std::vec::Vec<u8>, 186 num_blocks: u64, 187 write_limit: Option<u64>, 188 } 189 190 impl BlockIo { 191 pub fn new_memory(num_blocks: u64) -> Self { 192 Self { 193 storage: std::vec![0u8; num_blocks as usize * BLOCK_SIZE], 194 num_blocks, 195 write_limit: None, 196 } 197 } 198 199 pub fn clone_storage(&self) -> std::vec::Vec<u8> { 200 self.storage.clone() 201 } 202 203 pub fn from_storage(data: std::vec::Vec<u8>) -> Self { 204 let num_blocks = (data.len() / BLOCK_SIZE) as u64; 205 Self { 206 storage: data, 207 num_blocks, 208 write_limit: None, 209 } 210 } 211 212 pub fn raw_block_mut(&mut self, block_num: u64) -> Option<&mut [u8]> { 213 let start = block_num as usize * BLOCK_SIZE; 214 let end = start + BLOCK_SIZE; 215 match end <= self.storage.len() { 216 true => Some(&mut self.storage[start..end]), 217 false => None, 218 } 219 } 220 221 pub fn set_write_limit(&mut self, limit: Option<u64>) { 222 self.write_limit = limit; 223 } 224 225 pub fn read_blocks( 226 &mut self, 227 block_num: u64, 228 count: u16, 229 buf: &mut [u8], 230 ) -> Result<(), FsError> { 231 let start = block_num as usize * BLOCK_SIZE; 232 let len = count as usize * BLOCK_SIZE; 233 let end = start + len; 234 match end <= self.storage.len() { 235 true => { 236 let copy_len = len.min(buf.len()); 237 buf[..copy_len].copy_from_slice(&self.storage[start..start + copy_len]); 238 Ok(()) 239 } 240 false => Err(FsError::InvalidBlock), 241 } 242 } 243 244 pub fn write_blocks( 245 &mut self, 246 block_num: u64, 247 count: u16, 248 buf: &[u8], 249 ) -> Result<(), FsError> { 250 match self.write_limit { 251 Some(0) => return Err(FsError::Io(0xDEAD)), 252 Some(ref mut n) => *n -= 1, 253 None => {} 254 } 255 let start = block_num as usize * BLOCK_SIZE; 256 let len = count as usize * BLOCK_SIZE; 257 let end = start + len; 258 match end <= self.storage.len() { 259 true => { 260 let copy_len = len.min(buf.len()); 261 self.storage[start..start + copy_len].copy_from_slice(&buf[..copy_len]); 262 Ok(()) 263 } 264 false => Err(FsError::InvalidBlock), 265 } 266 } 267 268 pub fn flush(&mut self) -> Result<(), FsError> { 269 Ok(()) 270 } 271 272 pub fn sector_size(&self) -> u32 { 273 512 274 } 275 } 276} 277 278#[cfg(not(feature = "userspace"))] 279pub use mem_io::BlockIo;