Nothing to see here, move along
at main 224 lines 8.1 kB view raw
1#![cfg_attr(feature = "userspace", no_std)] 2#![cfg_attr(feature = "userspace", no_main)] 3#![allow(dead_code)] 4 5#[cfg(not(feature = "userspace"))] 6fn main() {} 7 8#[cfg(feature = "userspace")] 9mod service { 10 use lancer_lancerfs::dispatch::FsState; 11 use lancer_lancerfs::handle::HandleTableSet; 12 use lancer_lancerfs::{block_io, blockref_block_num, cache, commit, dispatch, ipc_proto, pool}; 13 use lancer_user::syscall; 14 15 const BLOCK_RING_BASE_SLOT: u64 = 64; 16 const BLOCK_RING_FRAME_COUNT: u64 = 16; 17 const NOTIF_SLOT: u64 = 3; 18 #[allow(dead_code)] 19 const DRIVER_NOTIF_SLOT: u64 = 4; 20 const CLIENT_RING_BASE_SLOT: u64 = 96; 21 const CLIENT_RING_FRAME_COUNT: u64 = 16; 22 const CLIENT_NOTIF_SLOT: u64 = 6; 23 24 const BLOCK_RING_VADDR: u64 = 0x5000_0000; 25 const CLIENT_RING_VADDR: u64 = 0x5010_0000; 26 const RING_DATA_OFFSET: usize = 8192; 27 const RING_DATA_PAGES: usize = 14; 28 29 const CLIENT_RING_DATA_OFFSET: usize = 8192; 30 const CLIENT_RING_DATA_PAGES: usize = 14; 31 32 static mut CACHE: cache::BlockCache = cache::BlockCache::new(); 33 static mut POOL: pool::NodePool = pool::NodePool::new(); 34 static mut HANDLES: HandleTableSet = HandleTableSet::new(); 35 36 fn mount(bio: &mut block_io::BlockIo, cache_ref: &mut cache::BlockCache) -> FsState { 37 lancer_user::show!(lancerfs, "reading superblocks"); 38 39 let sb_pair = match commit::load_validated_superblock_pair(bio) { 40 Ok(pair) => { 41 lancer_user::show!(lancerfs, "superblock pair loaded"); 42 pair 43 } 44 Err(_) => { 45 lancer_user::show!(lancerfs, error, "no valid superblock found"); 46 syscall::exit(); 47 } 48 }; 49 50 #[allow(clippy::deref_addrof)] 51 let pool_ref = unsafe { &mut *(&raw mut POOL) }; 52 53 let tree_root = sb_pair.active().tree_root; 54 let root_ref = match lancer_lancerfs::btree::btree_lookup( 55 pool_ref, cache_ref, bio, &tree_root, 1, None, 56 ) { 57 Ok(Some(r)) => r, 58 _ => { 59 lancer_user::show!(lancerfs, error, "root inode not found in metadata tree"); 60 syscall::exit(); 61 } 62 }; 63 pool_ref.clear_all(); 64 65 let root_block = blockref_block_num(&root_ref); 66 let root_inode = match lancer_lancerfs::file::read_inode(cache_ref, bio, root_block) { 67 Ok(inode) => inode, 68 Err(_) => { 69 lancer_user::show!(lancerfs, error, "failed to read root inode"); 70 syscall::exit(); 71 } 72 }; 73 74 { 75 let active = sb_pair.active(); 76 lancer_user::show!( 77 lancerfs, 78 "mounted {} blocks seq {} txn {} tree_root {:#x} freemap_root {:#x}", 79 active.total_blocks, 80 active.sequence, 81 active.transaction_id, 82 active.tree_root.physical_block_addr(), 83 active.freemap_root.physical_block_addr() 84 ); 85 } 86 87 let mut state = FsState::from_superblock_pair( 88 sb_pair, 89 root_block, 90 root_inode.object_id, 91 root_inode.generation, 92 ); 93 94 lancer_user::show!( 95 lancerfs, 96 "ditto allocable {} scrub cursor {}", 97 state.ditto.allocable_data_blocks(), 98 state.scrub.cursor() 99 ); 100 101 state.handles = unsafe { core::ptr::read(&raw const HANDLES) }; 102 state 103 } 104 105 #[unsafe(no_mangle)] 106 pub extern "C" fn lancer_main() -> ! { 107 lancer_user::show!(lancerfs, "starting"); 108 109 match (0..BLOCK_RING_FRAME_COUNT).all(|i| syscall::frame_map(BLOCK_RING_BASE_SLOT + i, BLOCK_RING_VADDR + i * 4096, 1) >= 0) { 110 true => {} 111 false => { 112 lancer_user::show!(lancerfs, error, "failed to map block ring"); 113 syscall::exit(); 114 } 115 } 116 117 let ring_base = BLOCK_RING_VADDR as *mut u8; 118 119 let request_ring = 120 unsafe { lancer_core::packet_ring::PacketRingWriter::init(ring_base, 4096, 32) }; 121 let response_ring = unsafe { 122 lancer_core::packet_ring::PacketRingReader::attach(ring_base.add(4096), 4096) 123 }; 124 let data_area = (BLOCK_RING_VADDR as usize + RING_DATA_OFFSET) as *mut u8; 125 let data_area_size = RING_DATA_PAGES * 4096; 126 127 lancer_user::show!(lancerfs, "waiting for nvme driver"); 128 syscall::notify_wait(NOTIF_SLOT); 129 130 let sector_size = 512u32; 131 let mut bio = unsafe { 132 block_io::BlockIo::init( 133 request_ring, 134 response_ring, 135 data_area, 136 data_area_size, 137 sector_size, 138 ) 139 }; 140 141 #[allow(clippy::deref_addrof)] 142 let cache_ref = unsafe { &mut *(&raw mut CACHE) }; 143 144 let mut fs_state = mount(&mut bio, cache_ref); 145 146 let has_client_ring = (0..CLIENT_RING_FRAME_COUNT).all(|i| syscall::frame_map(CLIENT_RING_BASE_SLOT + i, CLIENT_RING_VADDR + i * 4096, 1) >= 0); 147 148 let (client_request_ring, client_response_ring, client_data_area, client_data_area_size) = 149 match has_client_ring { 150 true => { 151 lancer_user::show!(lancerfs, "client ring mapped"); 152 let client_base = CLIENT_RING_VADDR as *mut u8; 153 let crr = unsafe { 154 lancer_core::packet_ring::PacketRingReader::attach(client_base, 4096) 155 }; 156 let crw = unsafe { 157 lancer_core::packet_ring::PacketRingWriter::init( 158 client_base.wrapping_add(4096), 159 4096, 160 32, 161 ) 162 }; 163 let cda = (CLIENT_RING_VADDR as usize + CLIENT_RING_DATA_OFFSET) as *mut u8; 164 let cds = CLIENT_RING_DATA_PAGES * 4096; 165 (Some(crr), Some(crw), cda, cds) 166 } 167 false => { 168 lancer_user::show!(lancerfs, "no client ring, standalone mode"); 169 (None, None, core::ptr::null_mut(), 0) 170 } 171 }; 172 173 #[allow(clippy::deref_addrof)] 174 let pool = unsafe { &mut *(&raw mut POOL) }; 175 176 let mut scratch = [0u8; 8192]; 177 let mut hash_table = [0u16; 1 << 12]; 178 179 lancer_user::show!(lancerfs, "entering dispatch loop"); 180 syscall::notify_signal(CLIENT_NOTIF_SLOT, 1); 181 182 let client_pid: u16 = 0; 183 let _ = fs_state.handles.install_root_handle( 184 client_pid, 185 fs_state.root_object_id, 186 fs_state.root_generation, 187 fs_state.root_inode_block, 188 ); 189 190 loop { 191 syscall::notify_wait(NOTIF_SLOT); 192 193 if let (Some(reader), Some(writer)) = (&client_request_ring, &client_response_ring) { 194 let mut req_buf = [0u8; 64]; 195 let mut processed = 0u32; 196 (0..64u32).for_each(|_| { 197 if let Some(len) = reader.try_pop(&mut req_buf) 198 && len >= ipc_proto::FsRequest::SIZE 199 && let Some(req) = ipc_proto::FsRequest::from_bytes(&req_buf) 200 { 201 let resp = dispatch::dispatch_request( 202 &req, 203 pool, 204 cache_ref, 205 &mut bio, 206 &mut fs_state, 207 client_data_area, 208 client_data_area_size, 209 client_pid, 210 &mut scratch, 211 &mut hash_table, 212 ); 213 let _ = writer.try_push(resp.as_bytes()); 214 processed += 1; 215 } 216 }); 217 218 if processed > 0 { 219 syscall::notify_signal(CLIENT_NOTIF_SLOT, 1); 220 } 221 } 222 } 223 } 224}