Changes in uspace/lib/ext4/libext4_filesystem.c [eb94d84:c1fd281] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_filesystem.c
reb94d84 rc1fd281 40 40 #include <malloc.h> 41 41 #include <ipc/vfs.h> 42 #include <align.h> 42 43 #include "libext4.h" 43 44 … … 250 251 } 251 252 253 /** Convert the absolute block number to group number 254 * 255 * @param sb Pointer to the superblock 256 * @param b Absolute block number 257 * 258 * @return Group number 259 */ 260 uint32_t ext4_filesystem_blockaddr2group(ext4_superblock_t *sb, uint64_t b) 261 { 262 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb); 263 uint32_t first_block = ext4_superblock_get_first_data_block(sb); 264 265 return (b - first_block) / blocks_per_group; 266 } 267 252 268 /** Initialize block bitmap in block group. 253 269 * … … 259 275 static int ext4_filesystem_init_block_bitmap(ext4_block_group_ref_t *bg_ref) 260 276 { 277 uint64_t itb; 278 uint32_t sz; 279 uint32_t i; 280 261 281 /* Load bitmap */ 262 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap( 282 ext4_superblock_t *sb = bg_ref->fs->superblock; 283 uint64_t bitmap_block_addr = ext4_block_group_get_block_bitmap( 284 bg_ref->block_group, bg_ref->fs->superblock); 285 uint64_t bitmap_inode_addr = ext4_block_group_get_inode_bitmap( 263 286 bg_ref->block_group, bg_ref->fs->superblock); 264 287 … … 272 295 273 296 /* Initialize all bitmap bits to zero */ 274 uint32_t block_size = ext4_superblock_get_block_size( bg_ref->fs->superblock);297 uint32_t block_size = ext4_superblock_get_block_size(sb); 275 298 memset(bitmap, 0, block_size); 276 299 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 300 /* Determine the number of reserved blocks in the group */ 301 uint32_t reserved_cnt = ext4_filesystem_bg_get_backup_blocks(bg_ref); 302 285 303 /* 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)304 for (uint32_t block = 0; block < reserved_cnt; ++block) 287 305 ext4_bitmap_set_bit(bitmap, block); 288 306 307 uint32_t bitmap_block_gid = ext4_filesystem_blockaddr2group(sb, 308 bitmap_block_addr); 309 if (bitmap_block_gid == bg_ref->index) { 310 ext4_bitmap_set_bit(bitmap, 311 ext4_filesystem_blockaddr2_index_in_group(sb, bitmap_block_addr)); 312 } 313 314 uint32_t bitmap_inode_gid = ext4_filesystem_blockaddr2group(sb, 315 bitmap_inode_addr); 316 if (bitmap_inode_gid == bg_ref->index) { 317 ext4_bitmap_set_bit(bitmap, 318 ext4_filesystem_blockaddr2_index_in_group(sb, bitmap_inode_addr)); 319 } 320 321 itb = ext4_block_group_get_inode_table_first_block(bg_ref->block_group, 322 sb); 323 sz = ext4_filesystem_bg_get_itable_size(sb, bg_ref); 324 325 for (i = 0; i < sz; ++i, ++itb) { 326 uint32_t gid = ext4_filesystem_blockaddr2group(sb, itb); 327 if (gid == bg_ref->index) { 328 ext4_bitmap_set_bit(bitmap, 329 ext4_filesystem_blockaddr2_index_in_group(sb, itb)); 330 } 331 } 332 289 333 bitmap_block->dirty = true; 290 334 … … 423 467 } 424 468 425 /* Initi tialize in-memory representation */469 /* Initialize in-memory representation */ 426 470 newref->block_group = newref->block->data + offset; 427 471 newref->fs = fs; … … 523 567 } 524 568 569 /** Get the size of the block group's inode table 570 * 571 * @param sb Pointer to the superblock 572 * @param bg_ref Pointer to the block group reference 573 * 574 * @return Size of the inode table in blocks. 575 */ 576 uint32_t ext4_filesystem_bg_get_itable_size(ext4_superblock_t *sb, 577 ext4_block_group_ref_t *bg_ref) 578 { 579 uint32_t itable_size; 580 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb); 581 uint16_t inode_table_item_size = ext4_superblock_get_inode_size(sb); 582 uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb); 583 uint32_t block_size = ext4_superblock_get_block_size(sb); 584 585 if (bg_ref->index < block_group_count - 1) { 586 itable_size = inodes_per_group * inode_table_item_size; 587 } else { 588 /* Last block group could be smaller */ 589 uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb); 590 itable_size = 591 (inodes_count_total - ((block_group_count - 1) * inodes_per_group)) * 592 inode_table_item_size; 593 } 594 595 return ROUND_UP(itable_size, block_size) / block_size; 596 } 597 598 /* Check if n is a power of p */ 599 static bool is_power_of(uint32_t n, unsigned p) 600 { 601 if (p == 1 && n != p) 602 return false; 603 604 while (n != p) { 605 if (n < p) 606 return false; 607 else if ((n % p) != 0) 608 return false; 609 610 n /= p; 611 } 612 613 return true; 614 } 615 616 /** Get the number of blocks used by superblock + gdt + reserved gdt backups 617 * 618 * @param bg Pointer to block group 619 * 620 * @return Number of blocks 621 */ 622 uint32_t ext4_filesystem_bg_get_backup_blocks(ext4_block_group_ref_t *bg) 623 { 624 uint32_t const idx = bg->index; 625 uint32_t r = 0; 626 bool has_backups = false; 627 ext4_superblock_t *sb = bg->fs->superblock; 628 629 /* First step: determine if the block group contains the backups */ 630 631 if (idx <= 1) 632 has_backups = true; 633 else { 634 if (ext4_superblock_has_feature_compatible(sb, 635 EXT4_FEATURE_COMPAT_SPARSE_SUPER2)) { 636 uint32_t g1, g2; 637 638 ext4_superblock_get_backup_groups_sparse2(sb, 639 &g1, &g2); 640 641 if (idx == g1 || idx == g2) 642 has_backups = true; 643 } else if (!ext4_superblock_has_feature_read_only(sb, 644 EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER)) { 645 /* Very old fs were all block groups have 646 * superblock and block descriptors backups. 647 */ 648 has_backups = true; 649 } else { 650 if ((idx & 1) && (is_power_of(idx, 3) || 651 is_power_of(idx, 5) || is_power_of(idx, 7))) 652 has_backups = true; 653 } 654 } 655 656 if (has_backups) { 657 uint32_t bg_count; 658 uint32_t bg_desc_sz; 659 uint32_t gdt_table; /* Size of the GDT in blocks */ 660 uint32_t block_size = ext4_superblock_get_block_size(sb); 661 662 /* Now we know that this block group has backups, 663 * we have to compute how many blocks are reserved 664 * for them 665 */ 666 667 if (idx == 0 && block_size == 1024) { 668 /* Special case for first group were the boot block 669 * resides 670 */ 671 r++; 672 } 673 674 /* This accounts for the superblock */ 675 r++; 676 677 /* Add the number of blocks used for the GDT */ 678 bg_count = ext4_superblock_get_block_group_count(sb); 679 bg_desc_sz = ext4_superblock_get_desc_size(sb); 680 gdt_table = ROUND_UP(bg_count * bg_desc_sz, block_size) / 681 block_size; 682 683 r += gdt_table; 684 685 /* And now the number of reserved GDT blocks */ 686 r += ext4_superblock_get_reserved_gdt_blocks(sb); 687 } 688 689 return r; 690 } 691 525 692 /** Put reference to block group. 526 693 * 527 * @ oaram ref Pointer for reference to be put back694 * @param ref Pointer for reference to be put back 528 695 * 529 696 * @return Error code
Note:
See TracChangeset
for help on using the changeset viewer.