Changes in uspace/lib/ext4/libext4_filesystem.c [eb94d84:fc22069] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_filesystem.c
reb94d84 rfc22069 40 40 #include <malloc.h> 41 41 #include <ipc/vfs.h> 42 #include <align.h> 43 #include <crypto.h> 42 44 #include "libext4.h" 43 45 … … 53 55 enum cache_mode cmode) 54 56 { 57 int rc; 55 58 ext4_superblock_t *temp_superblock = NULL; 56 59 … … 58 61 59 62 /* Initialize block library (4096 is size of communication channel) */ 60 int rc = block_init(EXCHANGE_SERIALIZE,fs->device, 4096);63 rc = block_init(fs->device, 4096); 61 64 if (rc != EOK) 62 65 goto err; … … 139 142 /* Release memory space for superblock */ 140 143 free(fs->superblock); 141 144 142 145 /* Finish work with block library */ 143 146 block_cache_fini(fs->device); … … 250 253 } 251 254 255 /** Convert the absolute block number to group number 256 * 257 * @param sb Pointer to the superblock 258 * @param b Absolute block number 259 * 260 * @return Group number 261 */ 262 uint32_t ext4_filesystem_blockaddr2group(ext4_superblock_t *sb, uint64_t b) 263 { 264 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb); 265 uint32_t first_block = ext4_superblock_get_first_data_block(sb); 266 267 return (b - first_block) / blocks_per_group; 268 } 269 252 270 /** Initialize block bitmap in block group. 253 271 * … … 259 277 static int ext4_filesystem_init_block_bitmap(ext4_block_group_ref_t *bg_ref) 260 278 { 279 uint64_t itb; 280 uint32_t sz; 281 uint32_t i; 282 261 283 /* Load bitmap */ 262 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap( 284 ext4_superblock_t *sb = bg_ref->fs->superblock; 285 uint64_t bitmap_block_addr = ext4_block_group_get_block_bitmap( 286 bg_ref->block_group, bg_ref->fs->superblock); 287 uint64_t bitmap_inode_addr = ext4_block_group_get_inode_bitmap( 263 288 bg_ref->block_group, bg_ref->fs->superblock); 264 289 … … 272 297 273 298 /* Initialize all bitmap bits to zero */ 274 uint32_t block_size = ext4_superblock_get_block_size( bg_ref->fs->superblock);299 uint32_t block_size = ext4_superblock_get_block_size(sb); 275 300 memset(bitmap, 0, block_size); 276 301 277 /* Determine first block and first data block in group */ 278 uint32_t first_idx = 0; 279 280 uint32_t first_data = ext4_balloc_get_first_data_block_in_group( 281 bg_ref->fs->superblock, bg_ref); 282 uint32_t first_data_idx = ext4_filesystem_blockaddr2_index_in_group( 283 bg_ref->fs->superblock, first_data); 284 302 /* Determine the number of reserved blocks in the group */ 303 uint32_t reserved_cnt = ext4_filesystem_bg_get_backup_blocks(bg_ref); 304 285 305 /* Set bits from to first block to first data block - 1 to one (allocated) */ 286 for (uint32_t block = first_idx; block < first_data_idx; ++block)306 for (uint32_t block = 0; block < reserved_cnt; ++block) 287 307 ext4_bitmap_set_bit(bitmap, block); 288 308 309 uint32_t bitmap_block_gid = ext4_filesystem_blockaddr2group(sb, 310 bitmap_block_addr); 311 if (bitmap_block_gid == bg_ref->index) { 312 ext4_bitmap_set_bit(bitmap, 313 ext4_filesystem_blockaddr2_index_in_group(sb, bitmap_block_addr)); 314 } 315 316 uint32_t bitmap_inode_gid = ext4_filesystem_blockaddr2group(sb, 317 bitmap_inode_addr); 318 if (bitmap_inode_gid == bg_ref->index) { 319 ext4_bitmap_set_bit(bitmap, 320 ext4_filesystem_blockaddr2_index_in_group(sb, bitmap_inode_addr)); 321 } 322 323 itb = ext4_block_group_get_inode_table_first_block(bg_ref->block_group, 324 sb); 325 sz = ext4_filesystem_bg_get_itable_size(sb, bg_ref); 326 327 for (i = 0; i < sz; ++i, ++itb) { 328 uint32_t gid = ext4_filesystem_blockaddr2group(sb, itb); 329 if (gid == bg_ref->index) { 330 ext4_bitmap_set_bit(bitmap, 331 ext4_filesystem_blockaddr2_index_in_group(sb, itb)); 332 } 333 } 334 289 335 bitmap_block->dirty = true; 290 336 … … 423 469 } 424 470 425 /* Initi tialize in-memory representation */471 /* Initialize in-memory representation */ 426 472 newref->block_group = newref->block->data + offset; 427 473 newref->fs = fs; … … 488 534 /* If checksum not supported, 0 will be returned */ 489 535 uint16_t crc = 0; 490 536 491 537 /* Compute the checksum only if the filesystem supports it */ 492 538 if (ext4_superblock_has_feature_read_only(sb, … … 501 547 502 548 /* Initialization */ 503 crc = crc16 (~0, sb->uuid, sizeof(sb->uuid));549 crc = crc16_ibm(~0, sb->uuid, sizeof(sb->uuid)); 504 550 505 551 /* Include index of block group */ 506 crc = crc16 (crc, (uint8_t *) &le_group, sizeof(le_group));552 crc = crc16_ibm(crc, (uint8_t *) &le_group, sizeof(le_group)); 507 553 508 554 /* Compute crc from the first part (stop before checksum field) */ 509 crc = crc16 (crc, (uint8_t *) bg, offset);555 crc = crc16_ibm(crc, (uint8_t *) bg, offset); 510 556 511 557 /* Skip checksum */ … … 516 562 EXT4_FEATURE_INCOMPAT_64BIT)) && 517 563 (offset < ext4_superblock_get_desc_size(sb))) 518 crc = crc16 (crc, ((uint8_t *) bg) + offset,564 crc = crc16_ibm(crc, ((uint8_t *) bg) + offset, 519 565 ext4_superblock_get_desc_size(sb) - offset); 520 566 } … … 523 569 } 524 570 571 /** Get the size of the block group's inode table 572 * 573 * @param sb Pointer to the superblock 574 * @param bg_ref Pointer to the block group reference 575 * 576 * @return Size of the inode table in blocks. 577 */ 578 uint32_t ext4_filesystem_bg_get_itable_size(ext4_superblock_t *sb, 579 ext4_block_group_ref_t *bg_ref) 580 { 581 uint32_t itable_size; 582 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb); 583 uint16_t inode_table_item_size = ext4_superblock_get_inode_size(sb); 584 uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb); 585 uint32_t block_size = ext4_superblock_get_block_size(sb); 586 587 if (bg_ref->index < block_group_count - 1) { 588 itable_size = inodes_per_group * inode_table_item_size; 589 } else { 590 /* Last block group could be smaller */ 591 uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb); 592 itable_size = 593 (inodes_count_total - ((block_group_count - 1) * inodes_per_group)) * 594 inode_table_item_size; 595 } 596 597 return ROUND_UP(itable_size, block_size) / block_size; 598 } 599 600 /* Check if n is a power of p */ 601 static bool is_power_of(uint32_t n, unsigned p) 602 { 603 if (p == 1 && n != p) 604 return false; 605 606 while (n != p) { 607 if (n < p) 608 return false; 609 else if ((n % p) != 0) 610 return false; 611 612 n /= p; 613 } 614 615 return true; 616 } 617 618 /** Get the number of blocks used by superblock + gdt + reserved gdt backups 619 * 620 * @param bg Pointer to block group 621 * 622 * @return Number of blocks 623 */ 624 uint32_t ext4_filesystem_bg_get_backup_blocks(ext4_block_group_ref_t *bg) 625 { 626 uint32_t const idx = bg->index; 627 uint32_t r = 0; 628 bool has_backups = false; 629 ext4_superblock_t *sb = bg->fs->superblock; 630 631 /* First step: determine if the block group contains the backups */ 632 633 if (idx <= 1) 634 has_backups = true; 635 else { 636 if (ext4_superblock_has_feature_compatible(sb, 637 EXT4_FEATURE_COMPAT_SPARSE_SUPER2)) { 638 uint32_t g1, g2; 639 640 ext4_superblock_get_backup_groups_sparse2(sb, 641 &g1, &g2); 642 643 if (idx == g1 || idx == g2) 644 has_backups = true; 645 } else if (!ext4_superblock_has_feature_read_only(sb, 646 EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) { 647 /* Very old fs were all block groups have 648 * superblock and block descriptors backups. 649 */ 650 has_backups = true; 651 } else { 652 if ((idx & 1) && (is_power_of(idx, 3) || 653 is_power_of(idx, 5) || is_power_of(idx, 7))) 654 has_backups = true; 655 } 656 } 657 658 if (has_backups) { 659 uint32_t bg_count; 660 uint32_t bg_desc_sz; 661 uint32_t gdt_table; /* Size of the GDT in blocks */ 662 uint32_t block_size = ext4_superblock_get_block_size(sb); 663 664 /* Now we know that this block group has backups, 665 * we have to compute how many blocks are reserved 666 * for them 667 */ 668 669 if (idx == 0 && block_size == 1024) { 670 /* Special case for first group were the boot block 671 * resides 672 */ 673 r++; 674 } 675 676 /* This accounts for the superblock */ 677 r++; 678 679 /* Add the number of blocks used for the GDT */ 680 bg_count = ext4_superblock_get_block_group_count(sb); 681 bg_desc_sz = ext4_superblock_get_desc_size(sb); 682 gdt_table = ROUND_UP(bg_count * bg_desc_sz, block_size) / 683 block_size; 684 685 r += gdt_table; 686 687 /* And now the number of reserved GDT blocks */ 688 r += ext4_superblock_get_reserved_gdt_blocks(sb); 689 } 690 691 return r; 692 } 693 525 694 /** Put reference to block group. 526 695 * 527 * @ oaram ref Pointer for reference to be put back696 * @param ref Pointer for reference to be put back 528 697 * 529 698 * @return Error code
Note:
See TracChangeset
for help on using the changeset viewer.