Nothing to see here, move along meow
0

Configure Feed

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

at main 27 kB View raw
1use crate::block_io::BlockIo; 2use crate::btree; 3use crate::bulkfree::{BulkfreePhase, BulkfreeState}; 4use crate::cache::BlockCache; 5use crate::cap::FsRights; 6use crate::commit; 7use crate::dir; 8use crate::dispatch::{FsState, dispatch_request}; 9use crate::error::FsError; 10use crate::file; 11use crate::integrity; 12use crate::ipc_proto::{FsRequest, FsResponse}; 13use crate::mkfs; 14use crate::ops; 15use crate::pool::NodePool; 16use crate::snapshot; 17use crate::transaction; 18use lancer_core::fs::{ 19 BLOCK_SIZE_MIN, BLOCK_SIZE_MIN_LOG2, BlockRef, BlockType, Compression, FREEMAP_BITS_PER_LEAF, 20 FreemapLeaf, INODE_SIZE, Inode, InodeType, 21}; 22use zerocopy::IntoBytes; 23 24const LZ4_HASH_SIZE: usize = 1 << 12; 25 26pub fn make_bio(num_blocks: u64) -> BlockIo { 27 BlockIo::new_memory(num_blocks) 28} 29 30pub fn make_cache() -> Box<BlockCache> { 31 unsafe { 32 let layout = std::alloc::Layout::new::<BlockCache>(); 33 let ptr = std::alloc::alloc_zeroed(layout) as *mut BlockCache; 34 assert!(!ptr.is_null()); 35 (*ptr).reset_lru(); 36 Box::from_raw(ptr) 37 } 38} 39 40pub fn make_pool() -> Box<NodePool> { 41 unsafe { 42 let layout = std::alloc::Layout::new::<NodePool>(); 43 let ptr = std::alloc::alloc_zeroed(layout) as *mut NodePool; 44 assert!(!ptr.is_null()); 45 (*ptr).clear_all(); 46 Box::from_raw(ptr) 47 } 48} 49 50pub struct TestFs { 51 pub bio: BlockIo, 52 pub cache: Box<BlockCache>, 53 pub pool: Box<NodePool>, 54 pub state: FsState, 55 pub scratch: Vec<u8>, 56 pub hash_table: Vec<u16>, 57 pub pending_tree_root: Option<BlockRef>, 58} 59 60fn mount_from_bio(bio: &mut BlockIo) -> FsState { 61 let sb_pair = commit::load_validated_superblock_pair(bio).unwrap(); 62 let tree_root = sb_pair.active().tree_root; 63 64 let mut cache = make_cache(); 65 let mut pool = make_pool(); 66 67 let root_ref = btree::btree_lookup(&mut pool, &mut cache, bio, &tree_root, 1, None) 68 .unwrap() 69 .expect("metadata tree must contain root inode (key=1)"); 70 71 let root_inode_block = crate::blockref_block_num(&root_ref); 72 let root_inode = file::read_inode(&mut cache, bio, root_inode_block).unwrap(); 73 74 drop(pool); 75 drop(cache); 76 77 FsState::from_superblock_pair( 78 sb_pair, 79 root_inode_block, 80 root_inode.object_id, 81 root_inode.generation, 82 ) 83} 84 85pub fn setup_fs(num_blocks: u64) -> TestFs { 86 let mut bio = make_bio(num_blocks); 87 mkfs::mkfs(&mut bio, num_blocks).unwrap(); 88 89 let state = mount_from_bio(&mut bio); 90 91 TestFs { 92 bio, 93 cache: make_cache(), 94 pool: make_pool(), 95 state, 96 scratch: vec![0u8; 8192], 97 hash_table: vec![0u16; LZ4_HASH_SIZE], 98 pending_tree_root: None, 99 } 100} 101 102pub fn with_fs<R>(num_blocks: u64, f: impl FnOnce(&mut TestFs) -> R) -> R { 103 let mut fs = setup_fs(num_blocks); 104 f(&mut fs) 105} 106 107impl TestFs { 108 pub fn next_txn(&self) -> u64 { 109 self.state.sb_pair.active().transaction_id.wrapping_add(1) 110 } 111 112 pub fn alloc_object_id(&mut self) -> u64 { 113 let id = self.state.next_object_id; 114 self.state.next_object_id += 1; 115 id 116 } 117 118 pub fn root_inode(&mut self) -> Inode { 119 file::read_inode(&mut self.cache, &mut self.bio, self.state.root_inode_block).unwrap() 120 } 121 122 pub fn read_inode(&mut self, block: u64) -> Inode { 123 file::read_inode(&mut self.cache, &mut self.bio, block).unwrap() 124 } 125 126 pub fn save_inode(&mut self, block: u64, inode: &Inode) { 127 file::write_inode_to_cache(&mut self.cache, &mut self.bio, block, inode).unwrap() 128 } 129 130 pub fn create_file(&mut self, parent_block: u64, name: &[u8]) -> (Inode, u64) { 131 let parent = self.read_inode(parent_block); 132 let txn = self.next_txn(); 133 let obj_id = self.alloc_object_id(); 134 let (updated_parent, child, child_block) = ops::file_create( 135 &mut self.pool, 136 &mut self.cache, 137 &mut self.bio, 138 &mut self.state.freemap, 139 &parent, 140 name, 141 InodeType::File, 142 txn, 143 obj_id, 144 ) 145 .unwrap(); 146 self.save_inode(parent_block, &updated_parent); 147 (child, child_block) 148 } 149 150 pub fn create_file_result( 151 &mut self, 152 parent_block: u64, 153 name: &[u8], 154 ) -> Result<(Inode, u64), FsError> { 155 let parent = self.read_inode(parent_block); 156 let txn = self.next_txn(); 157 let obj_id = self.alloc_object_id(); 158 let (updated_parent, child, child_block) = ops::file_create( 159 &mut self.pool, 160 &mut self.cache, 161 &mut self.bio, 162 &mut self.state.freemap, 163 &parent, 164 name, 165 InodeType::File, 166 txn, 167 obj_id, 168 )?; 169 self.save_inode(parent_block, &updated_parent); 170 Ok((child, child_block)) 171 } 172 173 pub fn write_file(&mut self, block: u64, offset: u64, data: &[u8]) -> Inode { 174 self.write_file_compressed(block, offset, data, Compression::None) 175 } 176 177 pub fn write_file_compressed( 178 &mut self, 179 block: u64, 180 offset: u64, 181 data: &[u8], 182 compression: Compression, 183 ) -> Inode { 184 let inode = self.read_inode(block); 185 let txn = self.next_txn(); 186 let dedup_roots = self.state.dedup_roots; 187 let ht: &mut [u16; LZ4_HASH_SIZE] = self.hash_table.as_mut_slice().try_into().unwrap(); 188 let (updated, _written, new_dedups) = file::file_write( 189 &mut self.pool, 190 &mut self.cache, 191 &mut self.bio, 192 &mut self.state.freemap, 193 &dedup_roots, 194 &inode, 195 offset, 196 data, 197 txn, 198 compression, 199 &mut self.scratch, 200 ht, 201 ) 202 .unwrap(); 203 self.state.dedup_roots = new_dedups; 204 self.save_inode(block, &updated); 205 updated 206 } 207 208 pub fn read_file(&mut self, block: u64, offset: u64, len: usize) -> Vec<u8> { 209 let inode = self.read_inode(block); 210 let mut buf = vec![0u8; len]; 211 let n = file::file_read( 212 &mut self.pool, 213 &mut self.cache, 214 &mut self.bio, 215 &inode, 216 offset, 217 &mut buf, 218 ) 219 .unwrap(); 220 buf.truncate(n); 221 buf 222 } 223 224 pub fn read_file_result( 225 &mut self, 226 block: u64, 227 offset: u64, 228 len: usize, 229 ) -> Result<Vec<u8>, FsError> { 230 let inode = self.read_inode(block); 231 let mut buf = vec![0u8; len]; 232 let n = file::file_read( 233 &mut self.pool, 234 &mut self.cache, 235 &mut self.bio, 236 &inode, 237 offset, 238 &mut buf, 239 )?; 240 buf.truncate(n); 241 Ok(buf) 242 } 243 244 pub fn mkdir(&mut self, parent_block: u64, name: &[u8]) -> (Inode, u64) { 245 let parent = self.read_inode(parent_block); 246 let txn = self.next_txn(); 247 let obj_id = self.alloc_object_id(); 248 let (updated_parent, child, child_block) = ops::mkdir( 249 &mut self.pool, 250 &mut self.cache, 251 &mut self.bio, 252 &mut self.state.freemap, 253 &parent, 254 name, 255 txn, 256 obj_id, 257 ) 258 .unwrap(); 259 self.save_inode(parent_block, &updated_parent); 260 (child, child_block) 261 } 262 263 pub fn rmdir(&mut self, parent_block: u64, name: &[u8]) -> Result<(), FsError> { 264 let parent = self.read_inode(parent_block); 265 let txn = self.next_txn(); 266 let updated_parent = ops::rmdir( 267 &mut self.pool, 268 &mut self.cache, 269 &mut self.bio, 270 &parent, 271 name, 272 txn, 273 )?; 274 self.save_inode(parent_block, &updated_parent); 275 Ok(()) 276 } 277 278 pub fn delete_file(&mut self, parent_block: u64, name: &[u8]) -> Result<(), FsError> { 279 let parent = self.read_inode(parent_block); 280 let txn = self.next_txn(); 281 let updated_parent = ops::file_delete( 282 &mut self.pool, 283 &mut self.cache, 284 &mut self.bio, 285 &parent, 286 name, 287 txn, 288 )?; 289 self.save_inode(parent_block, &updated_parent); 290 Ok(()) 291 } 292 293 pub fn commit(&mut self) { 294 let tree_root = self 295 .pending_tree_root 296 .take() 297 .unwrap_or_else(|| self.state.sb_pair.active().tree_root); 298 let dedup_roots = self.state.dedup_roots; 299 let snapshot_root = self.state.sb_pair.active().snapshot_root; 300 let scrub_cursor = self.state.scrub.cursor(); 301 let next_obj = self.state.next_object_id; 302 transaction::transaction_commit( 303 &mut self.pool, 304 &mut self.cache, 305 &mut self.bio, 306 &mut self.state.freemap, 307 &mut self.state.reserved, 308 &mut self.state.sb_pair, 309 &tree_root, 310 &dedup_roots, 311 &snapshot_root, 312 Some(&self.state.ditto), 313 scrub_cursor, 314 next_obj, 315 ) 316 .unwrap(); 317 self.state.dedup_roots = self.state.sb_pair.active().dedup_roots; 318 } 319 320 pub fn create_snapshot(&mut self, name: &[u8]) { 321 let tree_root = self.state.sb_pair.active().tree_root; 322 let dedup_roots = self.state.dedup_roots; 323 let snapshot_root = self.state.sb_pair.active().snapshot_root; 324 let scrub_cursor = self.state.scrub.cursor(); 325 let next_obj = self.state.next_object_id; 326 snapshot::create_snapshot( 327 &mut self.pool, 328 &mut self.cache, 329 &mut self.bio, 330 &mut self.state.freemap, 331 &mut self.state.reserved, 332 &mut self.state.sb_pair, 333 &tree_root, 334 &dedup_roots, 335 &snapshot_root, 336 name, 337 Some(&self.state.ditto), 338 scrub_cursor, 339 next_obj, 340 ) 341 .unwrap(); 342 self.state.dedup_roots = self.state.sb_pair.active().dedup_roots; 343 } 344 345 pub fn snapshot_lookup(&mut self, name: &[u8]) -> Option<snapshot::SnapshotRef> { 346 let snapshot_root = self.state.sb_pair.active().snapshot_root; 347 snapshot::snapshot_lookup( 348 &mut self.pool, 349 &mut self.cache, 350 &mut self.bio, 351 &snapshot_root, 352 name, 353 ) 354 .unwrap() 355 } 356 357 pub fn delete_snapshot(&mut self, name: &[u8]) { 358 let snapshot_root = self.state.sb_pair.active().snapshot_root; 359 let scrub_cursor = self.state.scrub.cursor(); 360 let next_obj = self.state.next_object_id; 361 snapshot::delete_snapshot( 362 &mut self.pool, 363 &mut self.cache, 364 &mut self.bio, 365 &mut self.state.freemap, 366 &mut self.state.reserved, 367 &mut self.state.sb_pair, 368 &snapshot_root, 369 name, 370 Some(&self.state.ditto), 371 scrub_cursor, 372 next_obj, 373 ) 374 .unwrap(); 375 } 376 377 pub fn root_block(&self) -> u64 { 378 self.state.root_inode_block 379 } 380 381 pub fn lookup_file(&mut self, parent_block: u64, name: &[u8]) -> Option<u64> { 382 let parent = self.read_inode(parent_block); 383 dir::dir_lookup( 384 &mut self.pool, 385 &mut self.cache, 386 &mut self.bio, 387 &parent, 388 name, 389 None, 390 ) 391 .ok() 392 .flatten() 393 .map(|br| crate::blockref_block_num(&br)) 394 } 395 396 pub fn resolve_path(&mut self, names: &[&[u8]]) -> Option<u64> { 397 names.iter().try_fold(self.root_block(), |block, name| { 398 self.lookup_file(block, name) 399 }) 400 } 401 402 pub fn count_allocated_blocks(&mut self) -> u64 { 403 let total_data = self.state.freemap.total_data_blocks(); 404 let total_leaves = total_data.div_ceil(FREEMAP_BITS_PER_LEAF as u64); 405 (0..total_leaves).fold(0u64, |acc, leaf_key| { 406 let leaf_block = crate::freemap::find_freemap_leaf_pub( 407 &mut self.cache, 408 &mut self.bio, 409 &self.state.freemap.root(), 410 leaf_key, 411 ) 412 .unwrap(); 413 let leaf_data = self.cache.cache_read(&mut self.bio, leaf_block).unwrap(); 414 let leaf = unsafe { &*(leaf_data.as_ptr() as *const FreemapLeaf) }; 415 let bits_in_leaf = { 416 let leaf_base = leaf_key * FREEMAP_BITS_PER_LEAF as u64; 417 let remaining = total_data.saturating_sub(leaf_base); 418 remaining.min(FREEMAP_BITS_PER_LEAF as u64) as usize 419 }; 420 let full_bytes = bits_in_leaf / 8; 421 let tail_bits = bits_in_leaf % 8; 422 let byte_count: u32 = leaf.bits[..full_bytes].iter().map(|b| b.count_ones()).sum(); 423 let tail_count = match tail_bits > 0 { 424 true => (leaf.bits[full_bytes] & ((1u8 << tail_bits) - 1)).count_ones(), 425 false => 0, 426 }; 427 acc + (byte_count + tail_count) as u64 428 }) 429 } 430 431 pub fn run_bulkfree(&mut self) { 432 let mut bf = BulkfreeState::new(); 433 let active = self.state.sb_pair.active(); 434 let roots: Vec<BlockRef> = [active.tree_root, active.snapshot_root] 435 .iter() 436 .copied() 437 .chain(active.dedup_roots.iter().copied()) 438 .filter(|r| !r.is_null()) 439 .collect(); 440 bf.start(&roots, active.transaction_id, 0); 441 while matches!(bf.phase(), BulkfreePhase::Marking) { 442 bf.mark_step(&mut self.cache, &mut self.bio).unwrap(); 443 } 444 while !bf.is_done() { 445 bf.sweep_step(&mut self.cache, &mut self.bio, &mut self.state.freemap) 446 .unwrap(); 447 } 448 } 449 450 pub fn commit_result(&mut self) -> Result<(), FsError> { 451 let tree_root = self 452 .pending_tree_root 453 .take() 454 .unwrap_or_else(|| self.state.sb_pair.active().tree_root); 455 let dedup_roots = self.state.dedup_roots; 456 let snapshot_root = self.state.sb_pair.active().snapshot_root; 457 let scrub_cursor = self.state.scrub.cursor(); 458 let next_obj = self.state.next_object_id; 459 let result = transaction::transaction_commit( 460 &mut self.pool, 461 &mut self.cache, 462 &mut self.bio, 463 &mut self.state.freemap, 464 &mut self.state.reserved, 465 &mut self.state.sb_pair, 466 &tree_root, 467 &dedup_roots, 468 &snapshot_root, 469 Some(&self.state.ditto), 470 scrub_cursor, 471 next_obj, 472 ); 473 match &result { 474 Ok(()) => self.state.dedup_roots = self.state.sb_pair.active().dedup_roots, 475 Err(_) => {} 476 } 477 result 478 } 479 480 pub fn remount(&mut self) { 481 self.cache = make_cache(); 482 self.pool = make_pool(); 483 self.state = mount_from_bio(&mut self.bio); 484 self.pending_tree_root = None; 485 } 486 487 pub fn write_file_cow(&mut self, name: &[u8], offset: u64, data: &[u8]) -> (Inode, u64) { 488 let txn = self.next_txn(); 489 let root_dir = self.read_inode(self.state.root_inode_block); 490 let file_ref = dir::dir_lookup( 491 &mut self.pool, 492 &mut self.cache, 493 &mut self.bio, 494 &root_dir, 495 name, 496 None, 497 ) 498 .unwrap() 499 .expect("file must exist for write_file_cow"); 500 let file_block = crate::blockref_block_num(&file_ref); 501 502 let file_inode = self.read_inode(file_block); 503 let dedup_roots = self.state.dedup_roots; 504 let ht: &mut [u16; LZ4_HASH_SIZE] = self.hash_table.as_mut_slice().try_into().unwrap(); 505 let (updated_file, _written, new_dedups) = file::file_write( 506 &mut self.pool, 507 &mut self.cache, 508 &mut self.bio, 509 &mut self.state.freemap, 510 &dedup_roots, 511 &file_inode, 512 offset, 513 data, 514 txn, 515 Compression::None, 516 &mut self.scratch, 517 ht, 518 ) 519 .unwrap(); 520 self.state.dedup_roots = new_dedups; 521 522 let new_file_block = file::cow_inode( 523 &mut self.cache, 524 &mut self.bio, 525 &mut self.state.freemap, 526 &updated_file, 527 ) 528 .unwrap(); 529 530 let new_file_phys = crate::block_num_to_phys(new_file_block); 531 let after_remove = dir::dir_remove( 532 &mut self.pool, 533 &mut self.cache, 534 &mut self.bio, 535 &root_dir, 536 name, 537 txn, 538 ) 539 .unwrap(); 540 let after_insert = dir::dir_insert( 541 &mut self.pool, 542 &mut self.cache, 543 &mut self.bio, 544 &after_remove, 545 name, 546 new_file_phys, 547 txn, 548 ) 549 .unwrap(); 550 551 let new_root_block = file::cow_inode( 552 &mut self.cache, 553 &mut self.bio, 554 &mut self.state.freemap, 555 &after_insert, 556 ) 557 .unwrap(); 558 self.state.root_inode_block = new_root_block; 559 560 self.update_metadata_tree(self.state.root_object_id, new_root_block); 561 562 (updated_file, new_file_block) 563 } 564 565 pub fn update_metadata_tree(&mut self, object_id: u64, new_inode_block: u64) { 566 let txn = self.next_txn(); 567 let tree_root = self 568 .pending_tree_root 569 .unwrap_or_else(|| self.state.sb_pair.active().tree_root); 570 571 let after_delete = btree::btree_delete( 572 &mut self.pool, 573 &mut self.cache, 574 &mut self.bio, 575 &tree_root, 576 object_id, 577 txn, 578 ) 579 .unwrap() 580 .unwrap_or(BlockRef::ZERO); 581 582 let mut inode_block_data = [0u8; BLOCK_SIZE_MIN as usize]; 583 let inode = self.read_inode(new_inode_block); 584 inode_block_data[..INODE_SIZE].copy_from_slice(inode.as_bytes()); 585 let hashes = integrity::compute_block_hashes(&inode_block_data); 586 587 let new_ref = BlockRef::new( 588 crate::block_num_to_phys(new_inode_block), 589 BLOCK_SIZE_MIN_LOG2, 590 object_id, 591 txn, 592 hashes.content_hash, 593 hashes.integrity_crc, 594 BlockType::Inode, 595 Compression::None, 596 0, 597 0, 598 ); 599 600 let new_tree_root = btree::btree_insert( 601 &mut self.pool, 602 &mut self.cache, 603 &mut self.bio, 604 &after_delete, 605 object_id, 606 new_ref, 607 txn, 608 ) 609 .unwrap(); 610 611 self.pending_tree_root = Some(new_tree_root); 612 } 613 614 pub fn writable_snapshot_commit( 615 &mut self, 616 name: &[u8], 617 new_snap_tree_root: &BlockRef, 618 snap_txn: u64, 619 ) { 620 let snapshot_root = self.state.sb_pair.active().snapshot_root; 621 let scrub_cursor = self.state.scrub.cursor(); 622 let next_obj = self.state.next_object_id; 623 snapshot::writable_snapshot_commit( 624 &mut self.pool, 625 &mut self.cache, 626 &mut self.bio, 627 &mut self.state.freemap, 628 &mut self.state.reserved, 629 &mut self.state.sb_pair, 630 &snapshot_root, 631 name, 632 new_snap_tree_root, 633 snap_txn, 634 Some(&self.state.ditto), 635 scrub_cursor, 636 next_obj, 637 ) 638 .unwrap(); 639 } 640 641 pub fn snapshot_create_file(&mut self, snap: &snapshot::SnapshotRef, name: &[u8]) -> BlockRef { 642 let txn = snap.snapshot_txn_id; 643 644 let root_entry = btree::btree_lookup( 645 &mut self.pool, 646 &mut self.cache, 647 &mut self.bio, 648 &snap.root_blockref, 649 self.state.root_object_id, 650 snap.txn_filter(), 651 ) 652 .unwrap() 653 .expect("snapshot must contain root inode"); 654 655 let root_block = crate::blockref_block_num(&root_entry); 656 let root_inode = self.read_inode(root_block); 657 658 let obj_id = self.alloc_object_id(); 659 let (updated_parent, _child, _child_block) = ops::file_create( 660 &mut self.pool, 661 &mut self.cache, 662 &mut self.bio, 663 &mut self.state.freemap, 664 &root_inode, 665 name, 666 InodeType::File, 667 txn, 668 obj_id, 669 ) 670 .unwrap(); 671 672 let new_root_block = file::cow_inode( 673 &mut self.cache, 674 &mut self.bio, 675 &mut self.state.freemap, 676 &updated_parent, 677 ) 678 .unwrap(); 679 680 let mut inode_block_data = [0u8; BLOCK_SIZE_MIN as usize]; 681 let new_root_inode = self.read_inode(new_root_block); 682 inode_block_data[..INODE_SIZE].copy_from_slice(new_root_inode.as_bytes()); 683 let hashes = integrity::compute_block_hashes(&inode_block_data); 684 685 let new_root_ref = BlockRef::new( 686 crate::block_num_to_phys(new_root_block), 687 BLOCK_SIZE_MIN_LOG2, 688 self.state.root_object_id, 689 txn, 690 hashes.content_hash, 691 hashes.integrity_crc, 692 BlockType::Inode, 693 Compression::None, 694 0, 695 0, 696 ); 697 698 let after_delete = btree::btree_delete( 699 &mut self.pool, 700 &mut self.cache, 701 &mut self.bio, 702 &snap.root_blockref, 703 self.state.root_object_id, 704 txn, 705 ) 706 .unwrap() 707 .unwrap_or(BlockRef::ZERO); 708 709 btree::btree_insert( 710 &mut self.pool, 711 &mut self.cache, 712 &mut self.bio, 713 &after_delete, 714 self.state.root_object_id, 715 new_root_ref, 716 txn, 717 ) 718 .unwrap() 719 } 720} 721 722pub struct DispatchTestFs { 723 pub fs: TestFs, 724 pub data_area: Vec<u8>, 725 pub client_pid: u16, 726 pub root_handle: u8, 727} 728 729pub fn setup_dispatch_fs(num_blocks: u64) -> DispatchTestFs { 730 let mut fs = setup_fs(num_blocks); 731 let root_handle = fs 732 .state 733 .handles 734 .install_root_handle( 735 0, 736 fs.state.root_object_id, 737 fs.state.root_generation, 738 fs.state.root_inode_block, 739 ) 740 .unwrap(); 741 742 DispatchTestFs { 743 fs, 744 data_area: vec![0u8; 8192], 745 client_pid: 0, 746 root_handle, 747 } 748} 749 750impl DispatchTestFs { 751 pub fn dispatch(&mut self, req: &FsRequest) -> FsResponse { 752 let hash_table: &mut [u16; LZ4_HASH_SIZE] = 753 self.fs.hash_table.as_mut_slice().try_into().unwrap(); 754 dispatch_request( 755 req, 756 &mut self.fs.pool, 757 &mut self.fs.cache, 758 &mut self.fs.bio, 759 &mut self.fs.state, 760 self.data_area.as_mut_ptr(), 761 self.data_area.len(), 762 self.client_pid, 763 &mut self.fs.scratch, 764 hash_table, 765 ) 766 } 767 768 pub fn dispatch_as(&mut self, client_pid: u16, req: &FsRequest) -> FsResponse { 769 let hash_table: &mut [u16; LZ4_HASH_SIZE] = 770 self.fs.hash_table.as_mut_slice().try_into().unwrap(); 771 dispatch_request( 772 req, 773 &mut self.fs.pool, 774 &mut self.fs.cache, 775 &mut self.fs.bio, 776 &mut self.fs.state, 777 self.data_area.as_mut_ptr(), 778 self.data_area.len(), 779 client_pid, 780 &mut self.fs.scratch, 781 hash_table, 782 ) 783 } 784 785 pub fn install_client(&mut self, pid: u16) -> u8 { 786 self.fs 787 .state 788 .handles 789 .install_root_handle( 790 pid, 791 self.fs.state.root_object_id, 792 self.fs.state.root_generation, 793 self.fs.state.root_inode_block, 794 ) 795 .unwrap() 796 } 797 798 pub fn dispatch_open(&mut self, dir_handle: u8, name: &[u8], mode: FsRights) -> FsResponse { 799 self.data_area[..name.len()].copy_from_slice(name); 800 let req = FsRequest::open(1, dir_handle, mode, 0, name.len() as u64); 801 self.dispatch(&req) 802 } 803 804 pub fn dispatch_mkdir(&mut self, dir_handle: u8, name: &[u8]) -> FsResponse { 805 self.data_area[..name.len()].copy_from_slice(name); 806 let req = FsRequest::mkdir(1, dir_handle, 0, name.len() as u64); 807 self.dispatch(&req) 808 } 809 810 pub fn dispatch_write(&mut self, handle: u8, offset: u64, data: &[u8]) -> FsResponse { 811 self.data_area[..data.len()].copy_from_slice(data); 812 let req = FsRequest::write(1, handle, offset, data.len() as u32, 0); 813 self.dispatch(&req) 814 } 815 816 pub fn dispatch_read(&mut self, handle: u8, offset: u64, len: u32) -> (FsResponse, Vec<u8>) { 817 self.data_area 818 .iter_mut() 819 .take(len as usize) 820 .for_each(|b| *b = 0); 821 let req = FsRequest::read(1, handle, offset, len, 0); 822 let resp = self.dispatch(&req); 823 let bytes_read = match resp.status { 824 0 => resp.val0 as usize, 825 _ => 0, 826 }; 827 let data = self.data_area[..bytes_read].to_vec(); 828 (resp, data) 829 } 830 831 pub fn dispatch_stat(&mut self, handle: u8) -> FsResponse { 832 let req = FsRequest::stat(1, handle); 833 self.dispatch(&req) 834 } 835 836 pub fn dispatch_close(&mut self, handle: u8) -> FsResponse { 837 let req = FsRequest::close(1, handle); 838 self.dispatch(&req) 839 } 840 841 pub fn dispatch_unlink(&mut self, dir_handle: u8, name: &[u8]) -> FsResponse { 842 self.data_area[..name.len()].copy_from_slice(name); 843 let req = FsRequest::unlink(1, dir_handle, 0, name.len() as u64); 844 self.dispatch(&req) 845 } 846 847 pub fn dispatch_readdir(&mut self, dir_handle: u8, cursor: u64, buf_len: usize) -> FsResponse { 848 let req = FsRequest::readdir(1, dir_handle, cursor, 0, buf_len as u64); 849 self.dispatch(&req) 850 } 851 852 pub fn dispatch_create_snapshot(&mut self, handle: u8, name: &[u8]) -> FsResponse { 853 self.data_area[..name.len()].copy_from_slice(name); 854 let req = FsRequest { 855 opcode: 9, 856 handle, 857 flags: 0, 858 _pad: 0, 859 tag: 1, 860 arg0: 0, 861 arg1: name.len() as u64, 862 arg2: 0, 863 }; 864 self.dispatch(&req) 865 } 866 867 pub fn dispatch_delete_snapshot(&mut self, handle: u8, name: &[u8]) -> FsResponse { 868 self.data_area[..name.len()].copy_from_slice(name); 869 let req = FsRequest { 870 opcode: 10, 871 handle, 872 flags: 0, 873 _pad: 0, 874 tag: 1, 875 arg0: 0, 876 arg1: name.len() as u64, 877 arg2: 0, 878 }; 879 self.dispatch(&req) 880 } 881 882 pub fn dispatch_sync(&mut self) -> FsResponse { 883 let req = FsRequest::sync(1); 884 self.dispatch(&req) 885 } 886 887 pub fn remount(&mut self) { 888 self.fs.remount(); 889 self.root_handle = self 890 .fs 891 .state 892 .handles 893 .install_root_handle( 894 self.client_pid, 895 self.fs.state.root_object_id, 896 self.fs.state.root_generation, 897 self.fs.state.root_inode_block, 898 ) 899 .unwrap(); 900 } 901}