Changes in uspace/lib/ext4/libext4_filesystem.c [fc22069:d1538a1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_filesystem.c
rfc22069 rd1538a1 39 39 #include <errno.h> 40 40 #include <malloc.h> 41 #include <ipc/vfs.h>42 #include <align.h>43 #include <crypto.h>44 41 #include "libext4.h" 45 42 … … 55 52 enum cache_mode cmode) 56 53 { 57 int rc;58 ext4_superblock_t *temp_superblock = NULL;59 60 54 fs->device = service_id; 61 55 62 56 /* Initialize block library (4096 is size of communication channel) */ 63 rc = block_init(fs->device, 4096);57 int rc = block_init(EXCHANGE_SERIALIZE, fs->device, 4096); 64 58 if (rc != EOK) 65 goto err;66 59 return rc; 60 67 61 /* Read superblock from device to memory */ 62 ext4_superblock_t *temp_superblock; 68 63 rc = ext4_superblock_read_direct(fs->device, &temp_superblock); 69 if (rc != EOK) 70 goto err_1; 71 64 if (rc != EOK) { 65 block_fini(fs->device); 66 return rc; 67 } 68 72 69 /* Read block size from superblock and check */ 73 70 uint32_t block_size = ext4_superblock_get_block_size(temp_superblock); 74 71 if (block_size > EXT4_MAX_BLOCK_SIZE) { 75 rc = ENOTSUP;76 goto err_1;77 } 78 72 block_fini(fs->device); 73 return ENOTSUP; 74 } 75 79 76 /* Initialize block caching by libblock */ 80 77 rc = block_cache_init(service_id, block_size, 0, cmode); 81 if (rc != EOK) 82 goto err_1; 83 78 if (rc != EOK) { 79 block_fini(fs->device); 80 return rc; 81 } 82 84 83 /* Compute limits for indirect block levels */ 85 84 uint32_t block_ids_per_block = block_size / sizeof(uint32_t); … … 92 91 fs->inode_blocks_per_level[i]; 93 92 } 94 93 95 94 /* Return loaded superblock */ 96 95 fs->superblock = temp_superblock; 97 96 98 97 uint16_t state = ext4_superblock_get_state(fs->superblock); 99 98 100 99 if (((state & EXT4_SUPERBLOCK_STATE_VALID_FS) != 101 100 EXT4_SUPERBLOCK_STATE_VALID_FS) || 102 101 ((state & EXT4_SUPERBLOCK_STATE_ERROR_FS) == 103 102 EXT4_SUPERBLOCK_STATE_ERROR_FS)) { 104 rc = ENOTSUP; 105 goto err_2; 106 } 107 103 block_cache_fini(fs->device); 104 block_fini(fs->device); 105 return ENOTSUP; 106 } 107 108 108 /* Mark system as mounted */ 109 109 ext4_superblock_set_state(fs->superblock, EXT4_SUPERBLOCK_STATE_ERROR_FS); 110 110 rc = ext4_superblock_write_direct(fs->device, fs->superblock); 111 if (rc != EOK) 112 goto err_2; 113 111 if (rc != EOK) { 112 block_cache_fini(fs->device); 113 block_fini(fs->device); 114 return rc; 115 } 116 114 117 uint16_t mnt_count = ext4_superblock_get_mount_count(fs->superblock); 115 118 ext4_superblock_set_mount_count(fs->superblock, mnt_count + 1); 116 119 117 120 return EOK; 118 119 err_2:120 block_cache_fini(fs->device);121 err_1:122 block_fini(fs->device);123 err:124 if (temp_superblock)125 ext4_superblock_release(temp_superblock);126 return rc;127 121 } 128 122 … … 142 136 /* Release memory space for superblock */ 143 137 free(fs->superblock); 144 138 145 139 /* Finish work with block library */ 146 140 block_cache_fini(fs->device); … … 253 247 } 254 248 255 /** Convert the absolute block number to group number256 *257 * @param sb Pointer to the superblock258 * @param b Absolute block number259 *260 * @return Group number261 */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 270 249 /** Initialize block bitmap in block group. 271 250 * … … 277 256 static int ext4_filesystem_init_block_bitmap(ext4_block_group_ref_t *bg_ref) 278 257 { 279 uint64_t itb;280 uint32_t sz;281 uint32_t i;282 283 258 /* Load 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( 259 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap( 288 260 bg_ref->block_group, bg_ref->fs->superblock); 289 261 … … 297 269 298 270 /* Initialize all bitmap bits to zero */ 299 uint32_t block_size = ext4_superblock_get_block_size( sb);271 uint32_t block_size = ext4_superblock_get_block_size(bg_ref->fs->superblock); 300 272 memset(bitmap, 0, block_size); 301 273 302 /* Determine the number of reserved blocks in the group */ 303 uint32_t reserved_cnt = ext4_filesystem_bg_get_backup_blocks(bg_ref); 304 274 /* Determine first block and first data block in group */ 275 uint32_t first_idx = 0; 276 277 uint32_t first_data = ext4_balloc_get_first_data_block_in_group( 278 bg_ref->fs->superblock, bg_ref); 279 uint32_t first_data_idx = ext4_filesystem_blockaddr2_index_in_group( 280 bg_ref->fs->superblock, first_data); 281 305 282 /* Set bits from to first block to first data block - 1 to one (allocated) */ 306 for (uint32_t block = 0; block < reserved_cnt; ++block)283 for (uint32_t block = first_idx; block < first_data_idx; ++block) 307 284 ext4_bitmap_set_bit(bitmap, block); 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 285 335 286 bitmap_block->dirty = true; 336 287 … … 469 420 } 470 421 471 /* Initi alize in-memory representation */422 /* Inititialize in-memory representation */ 472 423 newref->block_group = newref->block->data + offset; 473 424 newref->fs = fs; … … 534 485 /* If checksum not supported, 0 will be returned */ 535 486 uint16_t crc = 0; 536 487 537 488 /* Compute the checksum only if the filesystem supports it */ 538 489 if (ext4_superblock_has_feature_read_only(sb, … … 547 498 548 499 /* Initialization */ 549 crc = crc16 _ibm(~0, sb->uuid, sizeof(sb->uuid));500 crc = crc16(~0, sb->uuid, sizeof(sb->uuid)); 550 501 551 502 /* Include index of block group */ 552 crc = crc16 _ibm(crc, (uint8_t *) &le_group, sizeof(le_group));503 crc = crc16(crc, (uint8_t *) &le_group, sizeof(le_group)); 553 504 554 505 /* Compute crc from the first part (stop before checksum field) */ 555 crc = crc16 _ibm(crc, (uint8_t *) bg, offset);506 crc = crc16(crc, (uint8_t *) bg, offset); 556 507 557 508 /* Skip checksum */ … … 562 513 EXT4_FEATURE_INCOMPAT_64BIT)) && 563 514 (offset < ext4_superblock_get_desc_size(sb))) 564 crc = crc16 _ibm(crc, ((uint8_t *) bg) + offset,515 crc = crc16(crc, ((uint8_t *) bg) + offset, 565 516 ext4_superblock_get_desc_size(sb) - offset); 566 517 } … … 569 520 } 570 521 571 /** Get the size of the block group's inode table572 *573 * @param sb Pointer to the superblock574 * @param bg_ref Pointer to the block group reference575 *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 backups619 *620 * @param bg Pointer to block group621 *622 * @return Number of blocks623 */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 have648 * 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 reserved666 * for them667 */668 669 if (idx == 0 && block_size == 1024) {670 /* Special case for first group were the boot block671 * resides672 */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 694 522 /** Put reference to block group. 695 523 * 696 * @ param ref Pointer for reference to be put back524 * @oaram ref Pointer for reference to be put back 697 525 * 698 526 * @return Error code … … 968 796 } 969 797 970 rc = block_put(block); 971 if (rc != EOK) 972 return rc; 973 798 block_put(block); 974 799 rc = ext4_balloc_free_block(inode_ref, fblock); 975 800 if (rc != EOK) … … 1015 840 } 1016 841 1017 rc = block_put(subblock); 1018 if (rc != EOK) { 1019 block_put(block); 1020 return rc; 1021 } 842 block_put(subblock); 1022 843 } 1023 844 … … 1029 850 } 1030 851 1031 rc = block_put(block); 1032 if (rc != EOK) 1033 return rc; 1034 852 block_put(block); 1035 853 rc = ext4_balloc_free_block(inode_ref, fblock); 1036 854 if (rc != EOK)
Note:
See TracChangeset
for help on using the changeset viewer.