Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ext4/libext4_filesystem.c

    reb94d84 rc1fd281  
    4040#include <malloc.h>
    4141#include <ipc/vfs.h>
     42#include <align.h>
    4243#include "libext4.h"
    4344
     
    250251}
    251252
     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 */
     260uint32_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
    252268/** Initialize block bitmap in block group.
    253269 *
     
    259275static int ext4_filesystem_init_block_bitmap(ext4_block_group_ref_t *bg_ref)
    260276{
     277        uint64_t itb;
     278        uint32_t sz;
     279        uint32_t i;
     280
    261281        /* 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(
    263286            bg_ref->block_group, bg_ref->fs->superblock);
    264287       
     
    272295       
    273296        /* 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);
    275298        memset(bitmap, 0, block_size);
    276299       
    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
    285303        /* 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)
    287305                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
    289333        bitmap_block->dirty = true;
    290334       
     
    423467        }
    424468       
    425         /* Inititialize in-memory representation */
     469        /* Initialize in-memory representation */
    426470        newref->block_group = newref->block->data + offset;
    427471        newref->fs = fs;
     
    523567}
    524568
     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 */
     576uint32_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 */
     599static 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 */
     622uint32_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
    525692/** Put reference to block group.
    526693 *
    527  * @oaram ref Pointer for reference to be put back
     694 * @param ref Pointer for reference to be put back
    528695 *
    529696 * @return Error code
Note: See TracChangeset for help on using the changeset viewer.