1use core::ptr::copy_nonoverlapping;
7
8use alloc::boxed::Box;
9use alloc::string::String;
10use alloc::borrow::ToOwned;
11
12use crate::block_cache::BlockCache;
13
14use super::*;
15
16pub(crate) fn format(block_device: &mut dyn SyncBlockDevice) -> Result<(), FsError> {
17 let num_blocks = block_device.num_blocks();
18 if num_blocks < 2 {
19 return Err(FsError::InvalidArgument);
20 }
21
22 let num_blocks = num_blocks.min(u64::MAX - 1);
24
25 let mut block = Block::new_zeroed();
27 unsafe {
28 let fbh = block.get_mut::<SuperblockHeader>();
29 fbh.magic = MAGIC;
30 fbh.version = 1;
31 fbh.num_blocks = num_blocks;
32 fbh.free_blocks = num_blocks - 2;
33 fbh.generation = 1;
34 fbh.empty_area_start = 2; fbh.set_crc32();
36 fbh.validate()?;
37 }
38 block_device.write_block(0, block.as_bytes())?;
39
40 unsafe {
42 let root_dir = block.get_mut::<EntryMetadata>();
43 *root_dir = EntryMetadata::new(ROOT_DIR_ID, ROOT_DIR_ID);
44 root_dir.set_crc32();
45 }
46 block_device.write_block(1, block.as_bytes())?;
47
48 Ok(())
49}
50
51#[derive(Debug)]
52enum BlockType {
53 Metadata,
54 Data,
55 Links,
56 ListOfLinks,
57}
58
59pub struct SyncFileSystem {
60 superblock: Superblock,
61 blockcache: BlockCache,
62 num_blocks: u64,
63 error: Result<(), FsError>, }
65
66impl SyncFileSystem {
67 pub const fn root_dir_id() -> EntryId {
68 ROOT_DIR_ID
69 }
70
71 pub fn num_blocks(&self) -> u64 {
72 self.num_blocks
73 }
74
75 pub fn empty_blocks(&self) -> u64 {
76 self.superblock.header().free_blocks
77 }
78
79 pub fn open_fs(mut block_device: Box<dyn SyncBlockDevice>) -> Result<Self, FsError> {
80 let mut block = Box::new(Block::new_uninit());
81 block_device.read_block(0, block.as_bytes_mut())?;
82 let superblock = Superblock::from(block)?;
83
84 let num_blocks = superblock.header().num_blocks;
85 if num_blocks < 3 || num_blocks == u64::MAX || num_blocks > block_device.num_blocks() {
86 return Err(FsError::InvalidArgument);
87 }
88
89 let fbh = superblock.header();
90 if fbh.txn_meta_block != 0
91 || fbh.txn_data_block != 0
92 || fbh.txn_link_block != 0
93 || fbh.txn_list_of_links_block != 0
94 {
95 todo!("roll back or commit the TXN")
96 }
97
98 Ok(Self {
99 num_blocks,
100 superblock,
101 blockcache: BlockCache::new(block_device),
102 error: Ok(()),
103 })
104 }
105
106 pub fn add_file(&mut self, parent_id: EntryId, name: &str) -> Result<EntryId, FsError> {
108 self.add_directory_entry(parent_id, name, true)
109 }
110
111 pub fn add_directory(&mut self, parent_id: EntryId, name: &str) -> Result<EntryId, FsError> {
113 self.add_directory_entry(parent_id, name, false)
114 }
115
116 fn validate_new_entry(&mut self, parent_id: EntryId, name: &str) -> Result<(), FsError> {
118 self.error?;
119 validate_filename(name)?;
120 if parent_id.block_no >= self.num_blocks || parent_id.block_no < 1 {
121 return Err(FsError::InvalidArgument);
122 }
123 if self.find_entry_by_name(parent_id, name).is_ok() {
124 return Err(FsError::AlreadyExists);
125 }
126
127 let parent_block = self.blockcache.read(parent_id.block_no)?;
128 let meta = unsafe { parent_block.block().get::<EntryMetadata>() };
129 meta.validate_dir(parent_id)?;
130 if meta.size == MAX_DIR_ENTRIES {
131 return Err(FsError::TooLarge);
132 }
133
134 Ok(())
135 }
136
137 fn add_directory_entry_inner(
139 &mut self,
140 parent_id: EntryId,
141 child_id: EntryId,
142 child_name: &str,
143 ) -> Result<(), FsError> {
144 let sbh = self.superblock.header();
145 assert_ne!(TXN_TYPE_NONE, sbh.txn_type);
146 let parent_block = self.blockcache.get(parent_id.block_no);
147 let meta = unsafe { parent_block.block().get::<EntryMetadata>() };
148 let prev_size = meta.size;
149
150 if prev_size < MAX_ENTRIES_IN_META_BLOCK as u64 {
152 let parent_block = self.blockcache.get_mut(parent_id.block_no);
154 let meta = unsafe { parent_block.block_mut().get_mut::<EntryMetadata>() };
155 meta.size += 1;
156 meta.set_crc32();
157 parent_block
158 .block_mut()
159 .set_dir_entry((prev_size + 1) as usize, child_id, child_name);
160 self.blockcache.write(parent_id.block_no)?;
161 } else if prev_size < MAX_ENTRIES_ONLY_DATA_BLOCKS {
162 let need_new_block = prev_size == MAX_ENTRIES_IN_META_BLOCK
163 || (prev_size % MAX_ENTRIES_IN_DATA_BLOCK == 0);
164 if need_new_block {
165 let data_block_no = self.allocate_txn_block(BlockType::Data)?;
167
168 if prev_size == MAX_ENTRIES_IN_META_BLOCK {
170 let source_block_addr =
171 self.blockcache.get(parent_id.block_no).block() as *const Block as usize;
172 let data_block = self.blockcache.get_block_uninit(data_block_no);
173 for idx in 0..(MAX_ENTRIES_IN_META_BLOCK as usize) {
174 let source_block =
175 unsafe { (source_block_addr as *const Block).as_ref().unwrap() };
176
177 *data_block.block_mut().get_dir_entry_mut(idx) =
178 *source_block.get_dir_entry(idx + 1);
179 }
180
181 data_block.block_mut().set_dir_entry(
182 MAX_ENTRIES_IN_META_BLOCK as usize,
183 child_id,
184 child_name,
185 );
186 } else {
187 let data_block = self.blockcache.get_block_uninit(data_block_no);
188 data_block
189 .block_mut()
190 .set_dir_entry(0, child_id, child_name);
191 }
192 self.blockcache.write(data_block_no)?;
193
194 let parent_block = self.blockcache.get_mut(parent_id.block_no);
196 let meta = unsafe { parent_block.block_mut().get_mut::<EntryMetadata>() };
197 meta.size += 1;
198 meta.set_crc32();
199 parent_block
200 .block_mut()
201 .set_datablock_no_in_meta(prev_size / MAX_ENTRIES_IN_DATA_BLOCK, data_block_no);
202 self.blockcache.write(parent_id.block_no)?;
203 } else {
204 let data_block_idx = prev_size / MAX_ENTRIES_IN_DATA_BLOCK;
206 let parent_block = self.blockcache.get(parent_id.block_no);
207 let data_block_no = parent_block
208 .block()
209 .get_datablock_no_in_meta(data_block_idx);
210 let data_block = self.blockcache.read_mut(data_block_no)?;
211 data_block.block_mut().set_dir_entry(
212 (prev_size % MAX_ENTRIES_IN_DATA_BLOCK) as usize,
213 child_id,
214 child_name,
215 );
216 self.blockcache.write(data_block_no)?;
217 self.plus_one(parent_id.block_no)?;
218 }
219 } else {
220 let need_new_data_block = prev_size % MAX_ENTRIES_IN_DATA_BLOCK == 0;
221 let need_new_list_block = prev_size == MAX_ENTRIES_ONLY_DATA_BLOCKS
222 || (prev_size % MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST == 0);
223
224 if need_new_data_block {
225 let data_block_no = self.allocate_txn_block(BlockType::Data)?;
227 let data_block = self.blockcache.get_block_uninit(data_block_no);
228 data_block
229 .block_mut()
230 .set_dir_entry(0, child_id, child_name);
231 self.blockcache.write(data_block_no)?;
232
233 if need_new_list_block {
234 let link_block_no = self.allocate_txn_block(BlockType::Links)?;
235 if prev_size == MAX_ENTRIES_ONLY_DATA_BLOCKS {
236 let source_block_addr = self.blockcache.get(parent_id.block_no).block()
237 as *const Block
238 as usize;
239 let link_block = self.blockcache.get_block_uninit(link_block_no);
240 for idx in 0..MAX_LINKS_IN_META_BLOCK {
241 let source_block =
242 unsafe { (source_block_addr as *const Block).as_ref().unwrap() };
243
244 link_block.block_mut().set_datablock_no_in_link(
245 idx,
246 source_block.get_datablock_no_in_meta(idx),
247 );
248 }
249
250 link_block
251 .block_mut()
252 .set_datablock_no_in_link(MAX_LINKS_IN_META_BLOCK, data_block_no);
253 } else {
254 let link_block = self.blockcache.get_block_uninit(link_block_no);
255 link_block
256 .block_mut()
257 .set_datablock_no_in_link(0, data_block_no);
258 }
259 self.blockcache.write(link_block_no)?;
260 let parent_block = self.blockcache.get_mut(parent_id.block_no);
262 let meta = unsafe { parent_block.block_mut().get_mut::<EntryMetadata>() };
263 meta.size += 1;
264 meta.set_crc32();
265 parent_block.block_mut().set_datablock_no_in_meta(
266 prev_size / MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST,
267 link_block_no,
268 );
269 self.blockcache.write(parent_id.block_no)?;
270 } else {
271 let link_block_idx = prev_size / MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST;
273 let parent_block = self.blockcache.get(parent_id.block_no);
274 let link_block_no = parent_block
275 .block()
276 .get_datablock_no_in_meta(link_block_idx);
277 let link_block = self.blockcache.read_mut(link_block_no)?;
278 let data_block_idx = (prev_size % MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST)
279 / MAX_ENTRIES_IN_DATA_BLOCK;
280 link_block
281 .block_mut()
282 .set_datablock_no_in_link(data_block_idx, data_block_no);
283 self.blockcache.write(link_block_no)?;
284 self.plus_one(parent_id.block_no)?;
285 }
286 } else {
287 let link_block_idx = prev_size / MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST;
289 let parent_block = self.blockcache.get(parent_id.block_no);
290 let link_block_no = parent_block
291 .block()
292 .get_datablock_no_in_meta(link_block_idx);
293 let link_block = self.blockcache.read(link_block_no)?;
294 let data_block_idx = (prev_size % MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST)
295 / MAX_ENTRIES_IN_DATA_BLOCK;
296 let data_block_no = link_block.block().get_datablock_no_in_link(data_block_idx);
297
298 let data_block = self.blockcache.read_mut(data_block_no)?;
299 data_block.block_mut().set_dir_entry(
300 (prev_size % MAX_ENTRIES_IN_DATA_BLOCK) as usize,
301 child_id,
302 child_name,
303 );
304 self.blockcache.write(data_block_no)?;
305 self.plus_one(parent_id.block_no)?;
306 }
307 }
308
309 Ok(())
310 }
311
312 fn add_directory_entry(
313 &mut self,
314 parent_id: EntryId,
315 name: &str,
316 is_file: bool,
317 ) -> Result<EntryId, FsError> {
318 self.error?;
319 self.validate_new_entry(parent_id, name)?;
320
321 let mut generation = self.superblock.header().generation + 1;
330 if is_file && ((generation & 1) == 1) {
331 generation += 1; }
333 if (!is_file) && ((generation & 1) == 0) {
334 generation += 1; }
336
337 let sbh = self.superblock.header_mut();
338 sbh.generation = generation;
339 self.start_txn(TXN_TYPE_ADD_NODE, parent_id)?;
340
341 let block_no = self.allocate_txn_block(BlockType::Metadata)?;
343
344 let new_id = EntryId::new(block_no, generation);
346 let meta_block = self.blockcache.get_block_uninit(block_no);
347 let meta = unsafe { meta_block.block_mut().get_mut::<EntryMetadata>() };
348 *meta = EntryMetadata::new(new_id, parent_id);
349 meta.size = 0;
350 meta.set_crc32();
351 self.blockcache.write(block_no)?;
352
353 self.add_directory_entry_inner(parent_id, new_id, name)
354 .map_err(|e| {
355 let _ = self.make_error();
356 e
357 })?;
358
359 self.commit_txn()?;
361 Ok(new_id)
362 }
363
364 pub fn get_directory_entry(
366 &mut self,
367 parent: EntryId,
368 pos: u64,
369 ) -> Result<DirEntry, FsError> {
370 self.error?;
371 let parent_block = self.blockcache.read(parent.block_no)?;
372 let meta = unsafe { parent_block.block().get::<EntryMetadata>() };
373 meta.validate_dir(parent)?;
374 let num_entries = meta.size;
375
376 if pos as u64 >= meta.size {
377 return Err(FsError::NotFound);
378 }
379
380 if num_entries <= MAX_ENTRIES_IN_META_BLOCK {
381 return parent_block
382 .block()
383 .get_dir_entry((pos + 1) as usize)
384 .to_owned();
385 }
386
387 if num_entries <= MAX_ENTRIES_ONLY_DATA_BLOCKS {
388 let data_block_idx = pos / MAX_ENTRIES_IN_DATA_BLOCK;
389 let data_block_no = parent_block
390 .block()
391 .get_datablock_no_in_meta(data_block_idx);
392 return self
393 .blockcache
394 .read(data_block_no)?
395 .block()
396 .get_dir_entry((pos % MAX_ENTRIES_IN_DATA_BLOCK) as usize)
397 .to_owned();
398 }
399
400 let link_block_idx = pos / MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST;
401 let link_block_no = parent_block
402 .block()
403 .get_datablock_no_in_meta(link_block_idx);
404
405 let link_block = self.blockcache.read(link_block_no)?;
406 let data_block_idx =
407 (pos % MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST) / MAX_ENTRIES_IN_DATA_BLOCK;
408 let data_block_no = link_block.block().get_datablock_no_in_link(data_block_idx);
409
410 return self
411 .blockcache
412 .read(data_block_no)?
413 .block()
414 .get_dir_entry((pos % MAX_ENTRIES_IN_DATA_BLOCK) as usize)
415 .to_owned();
416 }
417
418 pub fn get_directory_entry_by_name(
419 &mut self,
420 parent: EntryId,
421 name: &str,
422 ) -> Result<DirEntry, FsError> {
423 self.error?;
424 let (block_no, entry_pos) = self.find_entry_by_name(parent, name)?;
425 let block = self.blockcache.read(block_no).unwrap();
426 Ok(block.block().get_dir_entry(entry_pos).to_owned()?)
427 }
428
429 pub fn get_num_entries(&mut self, dir: EntryId) -> Result<u64, FsError> {
431 self.error?;
432 let block = self.blockcache.read(dir.block_no)?;
433 let meta = unsafe { block.block().get::<EntryMetadata>() };
434 meta.validate_dir(dir)?;
435
436 Ok(meta.size as u64)
437 }
438
439 pub fn get_file_size(&mut self, file: EntryId) -> Result<u64, FsError> {
441 self.error?;
442 let block = self.blockcache.read(file.block_no)?;
443 let meta = unsafe { block.block().get::<EntryMetadata>() };
444 meta.validate_file(file)?;
445
446 Ok(meta.size)
447 }
448
449 pub fn stat(&mut self, entry: EntryId) -> Result<Attr, FsError> {
450 self.error?;
451 let block = self.blockcache.read(entry.block_no)?;
452 let meta = unsafe { block.block().get::<EntryMetadata>() };
453 meta.validate(entry)?;
454
455 Ok(meta.into())
456 }
457
458 pub fn set_file_size(&mut self, file_id: EntryId, new_size: u64) -> Result<(), FsError> {
459 self.error?;
460
461 loop {
463 let metadata_block = self.blockcache.read(file_id.block_no)?;
464 let meta = unsafe { metadata_block.block().get::<EntryMetadata>() };
465 meta.validate_file(file_id)?;
466 let prev_size = meta.size;
467 if new_size > prev_size {
468 return Err(FsError::InvalidArgument);
469 }
470 if new_size == prev_size {
471 return Ok(());
472 }
473
474 let mid_size = (prev_size - 1) & !(BLOCK_SIZE - 1);
475 debug_assert!(mid_size < prev_size);
476 debug_assert!((prev_size - mid_size) <= BLOCK_SIZE);
477 debug_assert_eq!(0, mid_size & (BLOCK_SIZE - 1));
478
479 let mid_size = if prev_size > MAX_BYTES_IN_META_BLOCK
481 && prev_size <= BLOCK_SIZE
482 && new_size <= MAX_BYTES_IN_META_BLOCK
483 {
484 new_size
485 } else {
486 mid_size
487 };
488
489 if (new_size > mid_size && new_size > MAX_BYTES_IN_META_BLOCK)
490 || prev_size <= MAX_BYTES_IN_META_BLOCK
491 {
492 let metadata_block = self.blockcache.get_mut(file_id.block_no);
494 let meta = unsafe { metadata_block.block_mut().get_mut::<EntryMetadata>() };
495 meta.size = new_size;
496 meta.set_crc32();
497 self.blockcache.write(file_id.block_no)?;
498 return Ok(());
499 }
500
501 if prev_size <= MAX_BYTES_ONLY_DATA_BLOCKS {
503 let block_idx = mid_size >> BLOCK_SIZE.ilog2();
505
506 let meta_block = self.blockcache.get(file_id.block_no);
507 let data_block_no = meta_block.block().get_datablock_no_in_meta(block_idx);
508
509 self.start_txn(TXN_TYPE_REMOVE_BYTES, file_id)?;
511 self.superblock.header_mut().txn_data_block = data_block_no;
512 self.save_superblock()?;
513
514 let metadata_block = self.blockcache.get_mut(file_id.block_no);
515 let meta = unsafe { metadata_block.block_mut().get_mut::<EntryMetadata>() };
516 meta.size = mid_size;
517 meta.set_crc32();
518 self.blockcache.write(file_id.block_no)?;
519
520 if (mid_size <= MAX_BYTES_IN_META_BLOCK) && (mid_size > 0) {
521 let data = *self.blockcache.read(data_block_no)?.block();
522 unsafe {
523 let metadata_block = self.blockcache.get_mut(file_id.block_no);
524 copy_nonoverlapping(
525 data.as_bytes().as_ptr(),
526 metadata_block
527 .block_mut()
528 .as_data_bytes_in_meta_mut()
529 .as_mut_ptr(),
530 MAX_BYTES_IN_META_BLOCK as usize,
531 );
532 }
533 self.blockcache.write(file_id.block_no)?;
534 }
535
536 self.free_txn_block(BlockType::Data)?;
537 self.commit_txn()?;
538 continue;
539 }
540
541 if prev_size <= MAX_BYTES_SINGLE_LEVEL_LIST_BLOCKS {
542 let link_block_idx = mid_size >> BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST.ilog2();
544 let meta_block = self.blockcache.get(file_id.block_no);
545 let link_block_no = meta_block.block().get_datablock_no_in_meta(link_block_idx);
546
547 let link_block = self.blockcache.read(link_block_no)?;
548 let data_block_idx =
549 (mid_size & (BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST - 1)) >> BLOCK_SIZE.ilog2();
550 let data_block_no = link_block.block().get_datablock_no_in_link(data_block_idx);
551
552 let need_to_free_link_block =
553 (data_block_idx == 0) || (mid_size == MAX_BYTES_ONLY_DATA_BLOCKS);
554
555 self.start_txn(TXN_TYPE_REMOVE_BYTES, file_id)?;
556 self.superblock.header_mut().txn_data_block = data_block_no;
557 if need_to_free_link_block {
558 self.superblock.header_mut().txn_link_block = link_block_no;
559 }
560 self.save_superblock()?;
561
562 let metadata_block = self.blockcache.get_mut(file_id.block_no);
563 let meta = unsafe { metadata_block.block_mut().get_mut::<EntryMetadata>() };
564 meta.size = mid_size;
565 meta.set_crc32();
566 self.blockcache.write(file_id.block_no)?;
567
568 if mid_size == MAX_BYTES_ONLY_DATA_BLOCKS {
569 let links = *self.blockcache.get(link_block_no).block();
570 let metadata_block = self.blockcache.get_mut(file_id.block_no);
571 for idx in 0..MAX_LINKS_IN_META_BLOCK {
572 metadata_block
573 .block_mut()
574 .set_datablock_no_in_meta(idx, links.get_datablock_no_in_link(idx));
575 }
576 self.blockcache.write(file_id.block_no)?;
577 }
578
579 self.free_txn_block(BlockType::Data)?;
580 if need_to_free_link_block {
581 self.free_txn_block(BlockType::Links)?;
582 }
583 self.commit_txn()?;
584 continue;
585 }
586
587 let list_of_links_block_idx =
589 mid_size >> BYTES_COVERED_BY_SECOND_LEVEL_BLOCKLIST.ilog2();
590 let meta_block = self.blockcache.get(file_id.block_no);
591 let list_of_links_block_no = meta_block
592 .block()
593 .get_datablock_no_in_meta(list_of_links_block_idx);
594
595 let link_block_idx = (mid_size & (BYTES_COVERED_BY_SECOND_LEVEL_BLOCKLIST - 1))
596 >> BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST.ilog2();
597 let list_of_links_block = self.blockcache.read(list_of_links_block_no)?;
598 let link_block_no = list_of_links_block
599 .block()
600 .get_datablock_no_in_link(link_block_idx);
601
602 let link_block = self.blockcache.read(link_block_no)?;
603 let data_block_idx =
604 (mid_size & (BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST - 1)) >> BLOCK_SIZE.ilog2();
605 let data_block_no = link_block.block().get_datablock_no_in_link(data_block_idx);
606
607 let need_to_free_link_block = data_block_idx == 0;
608 let need_to_free_list_of_links_block = need_to_free_link_block
609 && ((link_block_idx == 0) || (mid_size == MAX_BYTES_SINGLE_LEVEL_LIST_BLOCKS));
610
611 self.start_txn(TXN_TYPE_REMOVE_BYTES, file_id)?;
612 self.superblock.header_mut().txn_data_block = data_block_no;
613 if need_to_free_link_block {
614 self.superblock.header_mut().txn_link_block = link_block_no;
615 }
616 if need_to_free_list_of_links_block {
617 self.superblock.header_mut().txn_list_of_links_block = list_of_links_block_no;
618 }
619 self.save_superblock()?;
620
621 let metadata_block = self.blockcache.get_mut(file_id.block_no);
622 let meta = unsafe { metadata_block.block_mut().get_mut::<EntryMetadata>() };
623 meta.size = mid_size;
624 meta.set_crc32();
625 self.blockcache.write(file_id.block_no)?;
626
627 if mid_size == MAX_BYTES_SINGLE_LEVEL_LIST_BLOCKS {
628 let list_of_links = *self.blockcache.get(list_of_links_block_no).block();
629 let metadata_block = self.blockcache.get_mut(file_id.block_no);
630 for idx in 0..MAX_LINKS_IN_META_BLOCK {
631 metadata_block
632 .block_mut()
633 .set_datablock_no_in_meta(idx, list_of_links.get_datablock_no_in_link(idx));
634 }
635 self.blockcache.write(file_id.block_no)?;
636 }
637
638 self.free_txn_block(BlockType::Data)?;
639 if need_to_free_link_block {
640 self.free_txn_block(BlockType::Links)?;
641 }
642 if need_to_free_list_of_links_block {
643 self.free_txn_block(BlockType::ListOfLinks)?;
644 }
645 self.commit_txn()?;
646 continue;
647 }
648 }
649
650 pub fn get_parent(&mut self, entry_id: EntryId) -> Result<Option<EntryId>, FsError> {
651 if entry_id == ROOT_DIR_ID {
652 return Ok(None);
653 }
654
655 let block = self.blockcache.read(entry_id.block_no)?;
656 let meta = unsafe { block.block().get::<EntryMetadata>() };
657 meta.validate(entry_id)?;
658
659 Ok(Some(meta.parent_id))
660 }
661
662 pub fn get_name(&mut self, entry_id: EntryId) -> Result<String, FsError> {
663 if entry_id == ROOT_DIR_ID {
664 return Ok("/".to_owned());
665 }
666
667 let block = self.blockcache.read(entry_id.block_no)?;
668 let meta = unsafe { block.block().get::<EntryMetadata>() };
669
670 meta.validate(entry_id)?;
671
672 let parent_id = meta.parent_id;
673 let (block_no, entry_pos) = self.find_entry_by_id(parent_id, entry_id)?;
674 let block = self.blockcache.get(block_no);
675 let dir_entry = block.block().get_dir_entry(entry_pos);
676 Ok(dir_entry.to_owned()?.name)
677 }
678
679 pub fn move_rename(
680 &mut self,
681 entry_id: EntryId,
682 new_parent: EntryId,
683 new_name: &str,
684 ) -> Result<(), FsError> {
685 self.error?;
686 #[cfg(debug_assertions)]
687 {
688 let block = self.blockcache.read(entry_id.block_no)?;
689 let meta = unsafe { block.block().get::<EntryMetadata>() };
690 meta.validate(entry_id).unwrap();
691 let block = self.blockcache.read(new_parent.block_no)?;
692 let meta = unsafe { block.block().get::<EntryMetadata>() };
693 meta.validate(new_parent).unwrap();
694 }
695 self.validate_new_entry(new_parent, new_name)?;
696 if entry_id.block_no == ROOT_DIR_ID.block_no {
697 return Err(FsError::InvalidArgument);
698 }
699 let block = self.blockcache.read(entry_id.block_no)?;
700 let meta = unsafe { block.block().get::<EntryMetadata>() };
701 meta.validate(entry_id)?;
702 let old_parent = meta.parent_id;
703
704 if old_parent == new_parent {
705 let (block_no, entry_pos) = self.find_entry_by_id(old_parent, entry_id)?;
706 let block = self.blockcache.get_mut(block_no);
707 block
708 .block_mut()
709 .get_dir_entry_mut(entry_pos)
710 .set_name(new_name);
711 self.blockcache.write(block_no)?;
712 return Ok(());
713 }
714
715 self.start_txn(TXN_TYPE_MOVE, old_parent)?;
716 self.superblock.header_mut().txn_meta_block = entry_id.block_no;
717 self.save_superblock()?;
718
719 let block = self.blockcache.get_mut(entry_id.block_no);
720 let meta = unsafe { block.block_mut().get_mut::<EntryMetadata>() };
721 meta.parent_id = new_parent;
722 meta.set_crc32();
723 self.blockcache.write(entry_id.block_no)?;
724
725 #[cfg(debug_assertions)]
726 {
727 let block = self.blockcache.read(entry_id.block_no)?;
728 let meta = unsafe { block.block().get::<EntryMetadata>() };
729 meta.validate(entry_id).unwrap();
730 }
731
732 self.add_directory_entry_inner(new_parent, entry_id, new_name)
734 .map_err(|e| {
735 let _ = self.make_error();
736 e
737 })?;
738
739 #[cfg(debug_assertions)]
740 {
741 let block = self.blockcache.read(entry_id.block_no)?;
742 let meta = unsafe { block.block().get::<EntryMetadata>() };
743 meta.validate(entry_id).unwrap();
744 let block = self.blockcache.read(old_parent.block_no)?;
745 let meta = unsafe { block.block().get::<EntryMetadata>() };
746 meta.validate(old_parent).unwrap();
747 let block = self.blockcache.read(new_parent.block_no)?;
748 let meta = unsafe { block.block().get::<EntryMetadata>() };
749 meta.validate(new_parent).unwrap();
750 }
751
752 let sbh = self.superblock.header_mut();
754 sbh.txn_data_block = 0;
755 sbh.txn_link_block = 0;
756 sbh.txn_list_of_links_block = 0;
757
758 #[cfg(debug_assertions)]
759 {
760 let block = self.blockcache.read(entry_id.block_no)?;
761 let meta = unsafe { block.block().get::<EntryMetadata>() };
762 meta.validate(entry_id).unwrap();
763 }
764
765 self.remove_directory_entry_inner(old_parent, entry_id)
766 .map_err(|e| {
767 let _ = self.make_error();
768 e
769 })?;
770 if self.superblock.header().txn_link_block != 0 {
771 self.free_txn_block(BlockType::Links)?;
772 }
773 if self.superblock.header().txn_data_block != 0 {
774 self.free_txn_block(BlockType::Data)?;
775 }
776
777 #[cfg(debug_assertions)]
778 {
779 let block = self.blockcache.read(entry_id.block_no)?;
780 let meta = unsafe { block.block().get::<EntryMetadata>() };
781 meta.validate(entry_id).unwrap();
782 let block = self.blockcache.read(old_parent.block_no)?;
783 let meta = unsafe { block.block().get::<EntryMetadata>() };
784 meta.validate(old_parent).unwrap();
785 let block = self.blockcache.read(new_parent.block_no)?;
786 let meta = unsafe { block.block().get::<EntryMetadata>() };
787 meta.validate(new_parent).unwrap();
788 }
789
790 self.commit_txn()?;
791 #[cfg(debug_assertions)]
792 {
793 let block = self.blockcache.read(entry_id.block_no)?;
794 let meta = unsafe { block.block().get::<EntryMetadata>() };
795 meta.validate(entry_id).unwrap();
796 }
797
798 Ok(())
799 }
800
801 pub fn remove(&mut self, entry_id: EntryId) -> Result<(), FsError> {
802 self.error?;
803 if entry_id.block_no == ROOT_DIR_ID.block_no {
804 return Err(FsError::InvalidArgument);
805 }
806 let block = self.blockcache.read(entry_id.block_no)?;
807 let meta = unsafe { block.block().get::<EntryMetadata>() };
808 meta.validate(entry_id)?;
809 if meta.size > 0 {
810 #[cfg(debug_assertions)]
813 log::debug!("srfs-core: remove failed: non-empty entry");
814 return Err(FsError::TooLarge);
815 }
816 let parent_id = meta.parent_id;
817
818 self.start_txn(TXN_TYPE_REMOVE_NODE, parent_id)?;
820 let fbh = self.superblock.header_mut();
821 assert_eq!(0, fbh.txn_meta_block);
822 fbh.txn_meta_block = entry_id.block_no;
823
824 self.remove_directory_entry_inner(parent_id, entry_id)
825 .map_err(|e| {
826 let _ = self.make_error();
827 e
828 })?;
829
830 if self.superblock.header().txn_link_block != 0 {
832 self.free_txn_block(BlockType::Links)?;
833 }
834 if self.superblock.header().txn_data_block != 0 {
835 self.free_txn_block(BlockType::Data)?;
836 }
837 self.free_txn_block(BlockType::Metadata)?;
838 self.commit_txn()
839 }
840
841 fn remove_directory_entry_inner(
843 &mut self,
844 parent_id: EntryId,
845 child: EntryId,
846 ) -> Result<(), FsError> {
847 let sbh = self.superblock.header();
848 assert_ne!(TXN_TYPE_NONE, sbh.txn_type);
849
850 let (entry_block_no, entry_pos) = self.find_entry_by_id(parent_id, child)?;
852
853 let parent_block = self.blockcache.read(parent_id.block_no)?;
855 let parent_meta = unsafe { parent_block.block().get::<EntryMetadata>() };
856 parent_meta.validate_dir(parent_id)?;
857 let num_entries = parent_meta.size;
858 if num_entries <= MAX_ENTRIES_IN_META_BLOCK {
859 assert_eq!(entry_block_no, parent_id.block_no);
860 if (entry_pos as u64) < num_entries {
862 let parent_block = self.blockcache.get_mut(parent_id.block_no);
863 let last_entry = *parent_block.block().get_dir_entry(num_entries as usize);
864 *parent_block.block_mut().get_dir_entry_mut(entry_pos) = last_entry;
865 }
866 } else if num_entries <= MAX_ENTRIES_ONLY_DATA_BLOCKS {
867 let last_entry_block_idx = (num_entries - 1) / MAX_ENTRIES_IN_DATA_BLOCK;
868 let last_entry_block_no = parent_block
869 .block()
870 .get_datablock_no_in_meta(last_entry_block_idx);
871 let last_entry_idx = ((num_entries - 1) % MAX_ENTRIES_IN_DATA_BLOCK) as usize;
872
873 if (entry_block_no, entry_pos) != (last_entry_block_no, last_entry_idx) {
874 let last_entry_block = self.blockcache.read(last_entry_block_no)?;
875 let last_entry = *last_entry_block.block().get_dir_entry(last_entry_idx);
876 let entry_block = self.blockcache.read_mut(entry_block_no)?;
877 *entry_block.block_mut().get_dir_entry_mut(entry_pos) = last_entry;
878 self.blockcache.write(entry_block_no)?;
879 }
880
881 if last_entry_idx == 0 {
882 let fbh = self.superblock.header_mut();
884 assert_eq!(0, fbh.txn_data_block);
885 fbh.txn_data_block = last_entry_block_no;
886 self.save_superblock()?; }
888
889 if num_entries == (MAX_ENTRIES_IN_META_BLOCK + 1) {
890 let entry_block = *self.blockcache.get(entry_block_no).block();
892 let parent_block = self.blockcache.get_mut(parent_id.block_no);
893 for idx in 0..(MAX_ENTRIES_IN_META_BLOCK as usize) {
894 *parent_block.block_mut().get_dir_entry_mut(idx + 1) =
895 *entry_block.get_dir_entry(idx);
896 }
897 let fbh = self.superblock.header_mut();
901 assert_eq!(0, fbh.txn_data_block);
902 fbh.txn_data_block = last_entry_block_no;
903 self.save_superblock()?; }
905 } else {
906 let last_link_block_no = parent_block.block().get_datablock_no_in_meta(
907 (num_entries - 1) / MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST,
908 );
909
910 let last_link_block = self.blockcache.read(last_link_block_no)?;
911 let last_entry_block_idx = ((num_entries - 1)
912 % MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST)
913 / MAX_ENTRIES_IN_DATA_BLOCK;
914 let last_entry_block_no = last_link_block
915 .block()
916 .get_datablock_no_in_link(last_entry_block_idx);
917 let last_entry_idx = ((num_entries - 1) % MAX_ENTRIES_IN_DATA_BLOCK) as usize;
918
919 if (entry_block_no, entry_pos) != (last_entry_block_no, last_entry_idx) {
920 let last_entry_block = self.blockcache.read(last_entry_block_no)?;
921 let last_entry = *last_entry_block.block().get_dir_entry(last_entry_idx);
922 let entry_block = self.blockcache.read_mut(entry_block_no)?;
923 *entry_block.block_mut().get_dir_entry_mut(entry_pos) = last_entry;
924 self.blockcache.write(entry_block_no)?;
925 }
926
927 if last_entry_idx == 0 {
928 let fbh = self.superblock.header_mut();
930 assert_eq!(0, fbh.txn_data_block);
931 fbh.txn_data_block = last_entry_block_no;
932 self.save_superblock()?; }
934
935 if num_entries == (MAX_ENTRIES_ONLY_DATA_BLOCKS + 1) {
936 let link_block = self.blockcache.get(last_link_block_no);
938 let links: Block = *link_block.block();
939 let parent_block = self.blockcache.get_mut(parent_id.block_no);
940 for idx in 0..MAX_LINKS_IN_META_BLOCK {
941 parent_block
942 .block_mut()
943 .set_datablock_no_in_meta(idx, links.get_datablock_no_in_link(idx));
944 }
945 let fbh = self.superblock.header_mut();
949 assert_eq!(0, fbh.txn_link_block);
950 fbh.txn_link_block = last_link_block_no;
951 self.save_superblock()?; }
953
954 if (num_entries % MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST) == 1 {
955 let fbh = self.superblock.header_mut();
957 assert_eq!(0, fbh.txn_link_block);
958 fbh.txn_link_block = last_link_block_no;
959 self.save_superblock()?; }
961 }
962
963 let parent_block = self.blockcache.get_mut(parent_id.block_no);
964 let parent_meta = unsafe { parent_block.block_mut().get_mut::<EntryMetadata>() };
965 parent_meta.size -= 1;
966 parent_meta.set_crc32();
967 self.blockcache.write(parent_id.block_no)?;
968
969 Ok(())
970 }
971
972 pub fn write(&mut self, file_id: EntryId, offset: u64, buf: &[u8]) -> Result<usize, FsError> {
978 self.error?;
979 if file_id.kind() != EntryKind::File {
980 return Err(FsError::InvalidArgument);
981 }
982 let meta_block = self.blockcache.read(file_id.block_no)?;
983 let meta = unsafe { meta_block.block().get::<EntryMetadata>() };
984 meta.validate_file(file_id)?;
985 let prev_size = meta.size;
986 if offset > prev_size {
987 return Err(FsError::InvalidArgument);
988 }
989 let new_end = if offset == prev_size {
990 offset + (buf.len() as u64)
991 } else {
992 prev_size.min(offset + (buf.len() as u64))
993 };
994 let new_size = prev_size.max(new_end);
995 if new_size <= MAX_BYTES_IN_META_BLOCK {
996 let meta_block = self.blockcache.get_mut(file_id.block_no);
998 let meta = unsafe { meta_block.block_mut().get_mut::<EntryMetadata>() };
999
1000 meta.size = new_size;
1001 meta.set_crc32();
1002 unsafe {
1003 copy_nonoverlapping(
1004 buf.as_ptr(),
1005 (meta_block
1006 .block_mut()
1007 .as_data_bytes_in_meta_mut()
1008 .as_mut_ptr() as usize
1009 + (offset as usize)) as *mut u8,
1010 (new_end - offset) as usize,
1011 );
1012 }
1013 self.blockcache.write(file_id.block_no).map_err(|e| {
1014 let _ = self.make_error();
1015 e
1016 })?;
1017 return Ok((new_end - offset) as usize);
1018 }
1019
1020 if new_size == prev_size {
1021 return self.update_file(file_id, offset, buf);
1022 } else {
1023 return self.append(file_id, offset, buf);
1024 }
1025 }
1026
1027 pub fn read(
1028 &mut self,
1029 file_id: EntryId,
1030 offset: u64,
1031 buf: &mut [u8],
1032 ) -> Result<usize, FsError> {
1033 self.error?;
1034 if file_id.kind() != EntryKind::File {
1035 return Err(FsError::InvalidArgument);
1036 }
1037 let meta_block = self.blockcache.read(file_id.block_no)?;
1038 let meta = unsafe { meta_block.block().get::<EntryMetadata>() };
1039 meta.validate_file(file_id)?;
1040 let file_size = meta.size;
1041 if offset >= file_size {
1042 return Ok(0);
1043 }
1044 let end = file_size.min(offset + (buf.len() as u64));
1045 if file_size <= (MAX_BYTES_IN_META_BLOCK as u64) {
1046 unsafe {
1048 copy_nonoverlapping(
1049 (meta_block.block().as_data_bytes_in_meta().as_ptr() as usize
1050 + (offset as usize)) as *const u8,
1051 buf.as_mut_ptr(),
1052 (end - offset) as usize,
1053 );
1054 }
1055 return Ok((end - offset) as usize);
1056 }
1057
1058 let data_block_no = self.find_data_block(file_id, offset)?;
1059 let block_end = align_up(offset + 1, BLOCK_SIZE);
1060 let new_end = (offset + (buf.len() as u64)).min(block_end);
1061 let data_block = self.blockcache.read(data_block_no)?;
1062 unsafe {
1063 copy_nonoverlapping(
1064 (data_block.block().as_bytes().as_ptr() as usize
1065 + ((offset & (BLOCK_SIZE - 1)) as usize)) as *const u8,
1066 buf.as_mut_ptr(),
1067 (new_end - offset) as usize,
1068 );
1069 }
1070 return Ok((new_end - offset) as usize);
1071 }
1072
1073 fn append(&mut self, file_id: EntryId, offset: u64, buf: &[u8]) -> Result<usize, FsError> {
1074 self.error?;
1075 let meta_block = self.blockcache.get(file_id.block_no);
1080 let meta = unsafe { meta_block.block().get::<EntryMetadata>() };
1081 let prev_size = meta.size;
1082 assert_eq!(prev_size, offset);
1083 let new_size = if align_up(prev_size + 1, BLOCK_SIZE) >= prev_size + (buf.len() as u64) {
1084 prev_size + (buf.len() as u64)
1085 } else {
1086 align_up(prev_size + 1, BLOCK_SIZE)
1087 };
1088
1089 if prev_size <= MAX_BYTES_IN_META_BLOCK {
1091 assert!(new_size > MAX_BYTES_IN_META_BLOCK); let prev_bytes_start = meta_block.block().as_data_bytes_in_meta().as_ptr() as usize;
1095
1096 self.start_txn(TXN_TYPE_ADD_BYTES, file_id)?;
1098 let data_block_no = self.allocate_txn_block(BlockType::Data)?;
1099
1100 let data_block = self.blockcache.get_block_uninit(data_block_no);
1102 unsafe {
1103 copy_nonoverlapping(
1105 prev_bytes_start as *const u8,
1106 data_block.block_mut().as_bytes_mut().as_mut_ptr(),
1107 prev_size as usize,
1108 );
1109 copy_nonoverlapping(
1111 buf.as_ptr(),
1112 (data_block.block_mut().as_bytes_mut().as_ptr() as usize + (prev_size as usize))
1113 as *mut u8,
1114 (new_size - prev_size) as usize,
1115 );
1116 }
1117 self.blockcache.write(data_block_no).map_err(|e| {
1118 let _ = self.make_error();
1119 e
1120 })?;
1121
1122 let meta_block = self.blockcache.get_mut(file_id.block_no);
1124 meta_block
1125 .block_mut()
1126 .set_datablock_no_in_meta(0, data_block_no);
1127 let meta = unsafe { meta_block.block_mut().get_mut::<EntryMetadata>() };
1128 meta.size = new_size;
1129 meta.set_crc32();
1130 self.blockcache.write(file_id.block_no).map_err(|e| {
1131 let _ = self.make_error();
1132 e
1133 })?;
1134
1135 self.commit_txn()?;
1137 return Ok((new_size - prev_size) as usize);
1138 }
1139
1140 if align_up(prev_size, BLOCK_SIZE) >= new_size {
1141 let data_block_no = self.find_data_block(file_id, prev_size - 1)?;
1143
1144 let data_block = self.blockcache.read_mut(data_block_no)?;
1146 unsafe {
1147 copy_nonoverlapping(
1148 buf.as_ptr(),
1149 (data_block.block_mut().as_bytes_mut().as_mut_ptr() as usize
1150 + (offset & (BLOCK_SIZE - 1)) as usize) as *mut u8,
1151 (new_size - prev_size) as usize,
1152 );
1153 }
1154 self.blockcache.write(data_block_no)?;
1155
1156 let meta_block = self.blockcache.get_mut(file_id.block_no);
1158 let meta = unsafe { meta_block.block_mut().get_mut::<EntryMetadata>() };
1159 meta.size = new_size;
1160 meta.set_crc32();
1161 self.blockcache.write(file_id.block_no)?;
1162
1163 return Ok((new_size - prev_size) as usize);
1164 }
1165
1166 self.start_txn(TXN_TYPE_ADD_BYTES, file_id)?;
1168 let data_block_no = self.allocate_txn_block(BlockType::Data)?;
1169
1170 let data_block = self.blockcache.get_block_uninit(data_block_no);
1172 debug_assert_eq!(0, offset & (BLOCK_SIZE - 1));
1173 unsafe {
1174 copy_nonoverlapping(
1175 buf.as_ptr(),
1176 data_block.block_mut().as_bytes_mut().as_mut_ptr(),
1177 (new_size - prev_size) as usize,
1178 );
1179 }
1180 self.blockcache.write(data_block_no).map_err(|e| {
1181 let _ = self.make_error();
1182 e
1183 })?;
1184
1185 if new_size <= MAX_BYTES_ONLY_DATA_BLOCKS {
1186 let meta_block = self.blockcache.get_mut(file_id.block_no);
1188 meta_block
1189 .block_mut()
1190 .set_datablock_no_in_meta(prev_size >> BLOCK_SIZE.ilog2(), data_block_no);
1191 } else if new_size <= MAX_BYTES_SINGLE_LEVEL_LIST_BLOCKS {
1192 let need_new_link_block = (prev_size % BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST == 0)
1194 || (prev_size == MAX_BYTES_ONLY_DATA_BLOCKS);
1195
1196 if need_new_link_block {
1197 let link_block_no = self.allocate_txn_block(BlockType::Links).map_err(|e| {
1198 let _ = self.make_error();
1199 e
1200 })?;
1201
1202 let (link_block, data_block_idx) = if prev_size == MAX_BYTES_ONLY_DATA_BLOCKS {
1203 let meta_block = *self.blockcache.get(file_id.block_no).block();
1204 let bytes = meta_block.as_data_bytes_in_meta();
1205 let link_block = self.blockcache.get_block_uninit(link_block_no);
1206
1207 unsafe {
1208 copy_nonoverlapping(
1209 bytes.as_ptr(),
1210 link_block.block_mut().as_bytes_mut().as_mut_ptr(),
1211 bytes.len(),
1212 );
1213 }
1214
1215 (link_block, MAX_LINKS_IN_META_BLOCK)
1216 } else {
1217 (self.blockcache.get_block_uninit(link_block_no), 0)
1218 };
1219
1220 link_block
1221 .block_mut()
1222 .set_datablock_no_in_link(data_block_idx, data_block_no);
1223 self.blockcache.write(link_block_no).map_err(|e| {
1224 let _ = self.make_error();
1225 e
1226 })?;
1227
1228 let link_block_idx = prev_size >> BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST.ilog2();
1229 let meta_block = self.blockcache.get_mut(file_id.block_no);
1230 meta_block
1231 .block_mut()
1232 .set_datablock_no_in_meta(link_block_idx, link_block_no);
1233 } else {
1234 let link_block_idx = prev_size >> BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST.ilog2();
1235 let link_block_no = self
1236 .blockcache
1237 .get(file_id.block_no)
1238 .block()
1239 .get_datablock_no_in_meta(link_block_idx);
1240 let link_block = self.blockcache.read_mut(link_block_no);
1241 if let Err(err) = link_block {
1242 let _ = self.make_error();
1243 return Err(err);
1244 }
1245 let data_block_idx = (prev_size & (BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST - 1))
1246 >> BLOCK_SIZE.ilog2();
1247 link_block
1248 .unwrap()
1249 .block_mut()
1250 .set_datablock_no_in_link(data_block_idx, data_block_no);
1251 self.blockcache.write(link_block_no).map_err(|e| {
1252 let _ = self.make_error();
1253 e
1254 })?;
1255 }
1256 } else {
1257 let need_new_list_of_links_block =
1259 (prev_size % BYTES_COVERED_BY_SECOND_LEVEL_BLOCKLIST == 0)
1260 || (prev_size == MAX_BYTES_SINGLE_LEVEL_LIST_BLOCKS);
1261
1262 if need_new_list_of_links_block {
1263 let link_block_no = self.allocate_txn_block(BlockType::Links).map_err(|e| {
1265 let _ = self.make_error();
1266 e
1267 })?;
1268 let link_block = self.blockcache.get_block_uninit(link_block_no);
1269
1270 link_block
1271 .block_mut()
1272 .set_datablock_no_in_link(0, data_block_no);
1273 self.blockcache.write(link_block_no).map_err(|e| {
1274 let _ = self.make_error();
1275 e
1276 })?;
1277
1278 let list_of_links_block_no = self
1279 .allocate_txn_block(BlockType::ListOfLinks)
1280 .map_err(|e| {
1281 let _ = self.make_error();
1282 e
1283 })?;
1284 let (list_of_links_block, link_block_idx) =
1285 if prev_size == MAX_BYTES_SINGLE_LEVEL_LIST_BLOCKS {
1286 let meta_block = *self.blockcache.get(file_id.block_no).block();
1287 let bytes = meta_block.as_data_bytes_in_meta();
1288 let list_of_links_block =
1289 self.blockcache.get_block_uninit(list_of_links_block_no);
1290
1291 unsafe {
1292 copy_nonoverlapping(
1293 bytes.as_ptr(),
1294 list_of_links_block.block_mut().as_bytes_mut().as_mut_ptr(),
1295 bytes.len(),
1296 );
1297 }
1298
1299 (list_of_links_block, MAX_LINKS_IN_META_BLOCK)
1300 } else {
1301 (self.blockcache.get_block_uninit(list_of_links_block_no), 0)
1302 };
1303
1304 list_of_links_block
1305 .block_mut()
1306 .set_datablock_no_in_link(link_block_idx, link_block_no);
1307 self.blockcache.write(list_of_links_block_no).map_err(|e| {
1308 let _ = self.make_error();
1309 e
1310 })?;
1311
1312 let list_of_links_block_idx =
1313 prev_size >> BYTES_COVERED_BY_SECOND_LEVEL_BLOCKLIST.ilog2();
1314 let meta_block = self.blockcache.get_mut(file_id.block_no);
1315 meta_block
1316 .block_mut()
1317 .set_datablock_no_in_meta(list_of_links_block_idx, list_of_links_block_no);
1318 } else {
1319 let list_of_links_block_idx =
1320 prev_size >> BYTES_COVERED_BY_SECOND_LEVEL_BLOCKLIST.ilog2();
1321 let list_of_links_block_no = self
1322 .blockcache
1323 .get(file_id.block_no)
1324 .block()
1325 .get_datablock_no_in_meta(list_of_links_block_idx);
1326 if let Err(err) = self.blockcache.read(list_of_links_block_no) {
1328 let _ = self.make_error();
1329 return Err(err);
1330 }
1331
1332 let need_new_link_block = prev_size % BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST == 0;
1333 let link_block_idx = (prev_size & (BYTES_COVERED_BY_SECOND_LEVEL_BLOCKLIST - 1))
1334 >> BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST.ilog2();
1335
1336 if need_new_link_block {
1337 let link_block_no = self.allocate_txn_block(BlockType::Links).map_err(|e| {
1338 let _ = self.make_error();
1339 e
1340 })?;
1341 let link_block = self.blockcache.get_block_uninit(link_block_no);
1342
1343 link_block
1344 .block_mut()
1345 .set_datablock_no_in_link(0, data_block_no);
1346 self.blockcache.write(link_block_no).map_err(|e| {
1347 let _ = self.make_error();
1348 e
1349 })?;
1350
1351 let list_of_links_block = self.blockcache.get_mut(list_of_links_block_no);
1352 list_of_links_block
1353 .block_mut()
1354 .set_datablock_no_in_link(link_block_idx, link_block_no);
1355 self.blockcache.write(list_of_links_block_no).map_err(|e| {
1356 let _ = self.make_error();
1357 e
1358 })?;
1359 } else {
1360 let link_block_no = self
1361 .blockcache
1362 .get(list_of_links_block_no)
1363 .block()
1364 .get_datablock_no_in_link(link_block_idx);
1365 let link_block = self.blockcache.read_mut(link_block_no);
1366 if let Err(err) = link_block {
1367 let _ = self.make_error();
1368 return Err(err);
1369 }
1370 let data_block_idx = (prev_size & (BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST - 1))
1371 >> BLOCK_SIZE.ilog2();
1372 link_block
1373 .unwrap()
1374 .block_mut()
1375 .set_datablock_no_in_link(data_block_idx, data_block_no);
1376 self.blockcache.write(link_block_no).map_err(|e| {
1377 let _ = self.make_error();
1378 e
1379 })?;
1380 }
1381 }
1382 }
1383
1384 let meta_block = self.blockcache.get_mut(file_id.block_no);
1386 let meta = unsafe { meta_block.block_mut().get_mut::<EntryMetadata>() };
1387 meta.size = new_size;
1388 meta.set_crc32();
1389 self.blockcache.write(file_id.block_no).map_err(|e| {
1390 let _ = self.make_error();
1391 e
1392 })?;
1393
1394 self.commit_txn()?;
1395 return Ok((new_size - prev_size) as usize);
1396 }
1397
1398 fn update_file(&mut self, file_id: EntryId, offset: u64, buf: &[u8]) -> Result<usize, FsError> {
1399 let data_block_no = self.find_data_block(file_id, offset)?;
1400 let block_end = align_up(offset + 1, BLOCK_SIZE);
1401 let new_end = (offset + (buf.len() as u64)).min(block_end);
1402 let data_block = self.blockcache.read_mut(data_block_no)?;
1403 unsafe {
1404 copy_nonoverlapping(
1405 buf.as_ptr(),
1406 (data_block.block_mut().as_bytes_mut().as_ptr() as usize
1407 + ((offset & (BLOCK_SIZE - 1)) as usize)) as *mut u8,
1408 (new_end - offset) as usize,
1409 );
1410 }
1411 self.blockcache.write(data_block_no)?;
1412 return Ok((new_end - offset) as usize);
1413 }
1414
1415 fn find_data_block(&mut self, file_id: EntryId, offset: u64) -> Result<u64, FsError> {
1416 let meta_block = self.blockcache.get(file_id.block_no);
1417 let meta = unsafe { meta_block.block().get::<EntryMetadata>() };
1418 let file_size = meta.size;
1419 debug_assert!(file_size > MAX_BYTES_IN_META_BLOCK);
1420 debug_assert!(offset < file_size);
1421
1422 if file_size <= MAX_BYTES_ONLY_DATA_BLOCKS {
1423 let block_idx = offset >> BLOCK_SIZE.ilog2();
1425
1426 let meta_block = self.blockcache.get(file_id.block_no);
1427 return Ok(meta_block.block().get_datablock_no_in_meta(block_idx));
1428 }
1429
1430 if file_size <= MAX_BYTES_SINGLE_LEVEL_LIST_BLOCKS {
1431 let link_block_idx = offset >> BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST.ilog2();
1433 let meta_block = self.blockcache.get(file_id.block_no);
1434 let link_block_no = meta_block.block().get_datablock_no_in_meta(link_block_idx);
1435
1436 let link_block = self.blockcache.read(link_block_no)?;
1437 let data_block_idx =
1438 (offset & (BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST - 1)) >> BLOCK_SIZE.ilog2();
1439 return Ok(link_block.block().get_datablock_no_in_link(data_block_idx));
1440 }
1441
1442 let list_of_links_block_idx = offset >> BYTES_COVERED_BY_SECOND_LEVEL_BLOCKLIST.ilog2();
1444 let meta_block = self.blockcache.get(file_id.block_no);
1445 let list_of_links_block_no = meta_block
1446 .block()
1447 .get_datablock_no_in_meta(list_of_links_block_idx);
1448
1449 let list_of_links_block = self.blockcache.read(list_of_links_block_no)?;
1450 let link_block_idx = (offset & (BYTES_COVERED_BY_SECOND_LEVEL_BLOCKLIST - 1))
1451 >> BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST.ilog2();
1452 let link_block_no = list_of_links_block
1453 .block()
1454 .get_datablock_no_in_link(link_block_idx);
1455
1456 let link_block = self.blockcache.read(link_block_no)?;
1457 let data_block_idx =
1458 (offset & (BYTES_COVERED_BY_FIRST_LEVEL_BLOCKLIST - 1)) >> BLOCK_SIZE.ilog2();
1459 return Ok(link_block.block().get_datablock_no_in_link(data_block_idx));
1460 }
1461
1462 fn find_entry_by_id(
1463 &mut self,
1464 parent_id: EntryId,
1465 entry_id: EntryId,
1466 ) -> Result<(u64 , usize ), FsError> {
1467 self.find_entry(parent_id, |e| e.id == entry_id)
1468 }
1469
1470 fn find_entry_by_name(
1471 &mut self,
1472 parent_id: EntryId,
1473 name: &str,
1474 ) -> Result<(u64 , usize ), FsError> {
1475 self.find_entry(parent_id, |e| {
1476 if let Ok(s) = core::str::from_utf8(&e.name[0..(e.name_len as usize)]) {
1477 s == name
1478 } else {
1479 false
1480 }
1481 })
1482 }
1483
1484 fn find_entry<F>(
1485 &mut self,
1486 parent_id: EntryId,
1487 pred: F,
1488 ) -> Result<(u64 , usize ), FsError>
1489 where
1490 F: Fn(&DirEntryInternal) -> bool,
1491 {
1492 self.error?;
1493 let parent_block = self.blockcache.read(parent_id.block_no)?;
1494 let meta = unsafe { parent_block.block().get::<EntryMetadata>() };
1495 let valid = meta.validate_dir(parent_id);
1496 if valid.is_err() {
1497 let _ = self.make_error();
1498 return Err(valid.err().unwrap());
1499 }
1500
1501 let num_entries = meta.size;
1502 if num_entries <= MAX_ENTRIES_IN_META_BLOCK {
1503 for pos in 0..num_entries {
1504 let entry = parent_block.block().get_dir_entry((pos + 1) as usize);
1505 if pred(entry) {
1506 return Ok((parent_id.block_no, (pos + 1) as usize));
1507 }
1508 }
1509 return Err(FsError::NotFound);
1510 }
1511
1512 if num_entries <= MAX_ENTRIES_ONLY_DATA_BLOCKS {
1513 let num_blocks =
1514 (num_entries + MAX_ENTRIES_IN_DATA_BLOCK - 1) / MAX_ENTRIES_IN_DATA_BLOCK;
1515 assert!(num_blocks <= MAX_LINKS_IN_META_BLOCK);
1516
1517 let block_nos = *parent_block.block();
1519
1520 let mut curr_entry_idx = 0;
1521 for block_idx in 0..num_blocks {
1522 let block_no = block_nos.get_datablock_no_in_meta(block_idx);
1523 let block = self.blockcache.read(block_no)?;
1524
1525 for pos in 0..MAX_ENTRIES_IN_DATA_BLOCK {
1526 let entry = block.block().get_dir_entry(pos as usize);
1527 if pred(entry) {
1528 return Ok((block_no, pos as usize));
1529 }
1530 curr_entry_idx += 1;
1531 if curr_entry_idx >= num_entries {
1532 break;
1533 }
1534 }
1535 }
1536 return Err(FsError::NotFound);
1537 }
1538
1539 let num_link_blocks = (num_entries + MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST - 1)
1540 / MAX_ENTRIES_COVERED_BY_FIRST_LEVEL_BLOCKLIST;
1541 assert!(num_link_blocks <= MAX_LINKS_IN_META_BLOCK);
1542 let num_blocks = (num_entries + MAX_ENTRIES_IN_DATA_BLOCK - 1) / MAX_ENTRIES_IN_DATA_BLOCK;
1543
1544 let link_block_nos = *parent_block.block();
1546
1547 let mut curr_entry_idx = 0;
1548 let mut curr_block_idx = 0;
1549 for link_block_idx in 0..num_link_blocks {
1550 let link_block_no = link_block_nos.get_datablock_no_in_meta(link_block_idx);
1551 let link_block = self.blockcache.read(link_block_no)?;
1552 let data_block_nos = *link_block.block();
1553 for pos_block in 0..512 {
1554 let data_block_no = data_block_nos.get_datablock_no_in_link(pos_block);
1555 let block = self.blockcache.read(data_block_no)?;
1556 for pos in 0..MAX_ENTRIES_IN_DATA_BLOCK {
1557 let entry = block.block().get_dir_entry(pos as usize);
1558 if pred(entry) {
1559 return Ok((data_block_no, pos as usize));
1560 }
1561 curr_entry_idx += 1;
1562 if curr_entry_idx >= num_entries {
1563 break;
1564 }
1565 }
1566 curr_block_idx += 1;
1567 if curr_block_idx >= num_blocks {
1568 break;
1569 }
1570 }
1571 }
1572 return Err(FsError::NotFound);
1573 }
1574
1575 fn make_error(&mut self) -> Result<(), FsError> {
1576 assert!(self.error.is_ok());
1577 self.error = Err(FsError::ValidationFailed);
1578 return self.error;
1579 }
1580
1581 fn save_superblock(&mut self) -> Result<(), FsError> {
1582 assert!(self.error.is_ok());
1583 self.superblock.header_mut().set_crc32();
1584 self.blockcache
1585 .write_uncached_block(0, self.superblock.block())
1586 .map_err(|e| {
1587 let _ = self.make_error();
1588 e
1589 })
1590 }
1591
1592 fn plus_one(&mut self, block_no: u64) -> Result<(), FsError> {
1593 let block = self.blockcache.get_mut(block_no);
1594 let meta = unsafe { block.block_mut().get_mut::<EntryMetadata>() };
1595 meta.size += 1;
1596 meta.set_crc32();
1597 self.blockcache.write(block_no).map_err(|e| {
1598 let _ = self.make_error(); e
1600 })
1601 }
1602
1603 fn allocate_txn_block(&mut self, block_type: BlockType) -> Result<u64, FsError> {
1605 let fbh = self.superblock.header_mut();
1606 assert_ne!(0, fbh.txn_blocks_owner);
1607 if fbh.free_blocks == 0 {
1608 return Err(FsError::FsFull);
1609 }
1610
1611 #[cfg(debug_assertions)]
1612 match block_type {
1613 BlockType::Metadata => debug_assert_eq!(0, fbh.txn_meta_block),
1614 BlockType::Data => debug_assert_eq!(0, fbh.txn_data_block),
1615 BlockType::Links => debug_assert_eq!(0, fbh.txn_link_block),
1616 BlockType::ListOfLinks => debug_assert_eq!(0, fbh.txn_list_of_links_block),
1617 }
1618
1619 let new_block_no = if fbh.freelist_head == 0 {
1620 let new_block_no = fbh.empty_area_start;
1622 fbh.empty_area_start += 1;
1623 new_block_no
1624 } else {
1625 let new_block_no = fbh.freelist_head;
1627 let block = self.blockcache.read(new_block_no)?;
1628 fbh.freelist_head = *unsafe { block.block().get::<u64>() };
1629 if fbh.freelist_head >= fbh.num_blocks {
1630 log::error!("FS corrupted: bad freelist (1)");
1631 self.make_error()?;
1632 unreachable!()
1633 }
1634 new_block_no
1635 };
1636
1637 assert_ne!(new_block_no, 0);
1638 if new_block_no >= fbh.num_blocks {
1639 log::error!("FS corrupted: bad freelist (2)");
1640 self.make_error()?;
1641 unreachable!()
1642 }
1643 fbh.free_blocks -= 1;
1644 match block_type {
1645 BlockType::Metadata => fbh.txn_meta_block = new_block_no,
1646 BlockType::Data => fbh.txn_data_block = new_block_no,
1647 BlockType::Links => fbh.txn_link_block = new_block_no,
1648 BlockType::ListOfLinks => fbh.txn_list_of_links_block = new_block_no,
1649 }
1650 self.save_superblock()?;
1651
1652 Ok(new_block_no)
1653 }
1654
1655 fn free_txn_block(&mut self, block_type: BlockType) -> Result<(), FsError> {
1656 let sbh = self.superblock.header_mut();
1657 let block_no = match block_type {
1658 BlockType::Metadata => sbh.txn_meta_block,
1659 BlockType::Data => sbh.txn_data_block,
1660 BlockType::Links => sbh.txn_link_block,
1661 BlockType::ListOfLinks => sbh.txn_list_of_links_block,
1662 };
1663 assert_ne!(0, block_no);
1664 if sbh.empty_area_start == (block_no + 1) {
1665 sbh.empty_area_start -= 1;
1666 } else {
1667 let prev_head = sbh.freelist_head;
1668 let block = self.blockcache.get_block_uninit(block_no);
1669 unsafe { *block.block_mut().get_mut::<u64>() = prev_head };
1670 self.blockcache.write(block_no)?;
1671 }
1672
1673 match block_type {
1674 BlockType::Metadata => sbh.txn_meta_block = 0,
1675 BlockType::Data => sbh.txn_data_block = 0,
1676 BlockType::Links => sbh.txn_link_block = 0,
1677 BlockType::ListOfLinks => sbh.txn_list_of_links_block = 0,
1678 }
1679 sbh.free_blocks += 1;
1680 self.save_superblock()
1681 }
1682
1683 fn start_txn(&mut self, txn_type: u32, owner: EntryId) -> Result<(), FsError> {
1684 let sbh = self.superblock.header_mut();
1685 assert_eq!(TXN_TYPE_NONE, sbh.txn_type);
1686 assert_eq!(0, sbh.txn_blocks_owner);
1687 assert_eq!(0, sbh.txn_meta_block);
1688 assert_eq!(0, sbh.txn_data_block);
1689 assert_eq!(0, sbh.txn_link_block);
1690 assert_eq!(0, sbh.txn_list_of_links_block);
1691 sbh.txn_blocks_owner = owner.block_no;
1692 sbh.txn_type = txn_type;
1693
1694 self.save_superblock()
1695 }
1696
1697 fn commit_txn(&mut self) -> Result<(), FsError> {
1698 let sbh = self.superblock.header_mut();
1699 sbh.txn_meta_block = 0;
1700 sbh.txn_data_block = 0;
1701 sbh.txn_link_block = 0;
1702 sbh.txn_list_of_links_block = 0;
1703 sbh.txn_blocks_owner = 0;
1704 sbh.txn_type = TXN_TYPE_NONE;
1705 self.save_superblock()
1706 }
1707}