Ignore:
File:
1 edited

Legend:

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

    rfc22069 rd1538a1  
    3939#include <errno.h>
    4040#include <malloc.h>
    41 #include <ipc/vfs.h>
    42 #include <align.h>
    43 #include <crypto.h>
    4441#include "libext4.h"
    4542
     
    5552    enum cache_mode cmode)
    5653{
    57         int rc;
    58         ext4_superblock_t *temp_superblock = NULL;
    59 
    6054        fs->device = service_id;
    61 
     55       
    6256        /* 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);
    6458        if (rc != EOK)
    65                 goto err;
    66 
     59                return rc;
     60       
    6761        /* Read superblock from device to memory */
     62        ext4_superblock_t *temp_superblock;
    6863        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       
    7269        /* Read block size from superblock and check */
    7370        uint32_t block_size = ext4_superblock_get_block_size(temp_superblock);
    7471        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       
    7976        /* Initialize block caching by libblock */
    8077        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       
    8483        /* Compute limits for indirect block levels */
    8584        uint32_t block_ids_per_block = block_size / sizeof(uint32_t);
     
    9291                    fs->inode_blocks_per_level[i];
    9392        }
    94 
     93       
    9594        /* Return loaded superblock */
    9695        fs->superblock = temp_superblock;
    97 
     96       
    9897        uint16_t state = ext4_superblock_get_state(fs->superblock);
    99 
     98       
    10099        if (((state & EXT4_SUPERBLOCK_STATE_VALID_FS) !=
    101100            EXT4_SUPERBLOCK_STATE_VALID_FS) ||
    102101            ((state & EXT4_SUPERBLOCK_STATE_ERROR_FS) ==
    103102            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       
    108108        /* Mark system as mounted */
    109109        ext4_superblock_set_state(fs->superblock, EXT4_SUPERBLOCK_STATE_ERROR_FS);
    110110        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       
    114117        uint16_t mnt_count = ext4_superblock_get_mount_count(fs->superblock);
    115118        ext4_superblock_set_mount_count(fs->superblock, mnt_count + 1);
    116 
     119       
    117120        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;
    127121}
    128122
     
    142136        /* Release memory space for superblock */
    143137        free(fs->superblock);
    144 
     138       
    145139        /* Finish work with block library */
    146140        block_cache_fini(fs->device);
     
    253247}
    254248
    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 
    270249/** Initialize block bitmap in block group.
    271250 *
     
    277256static int ext4_filesystem_init_block_bitmap(ext4_block_group_ref_t *bg_ref)
    278257{
    279         uint64_t itb;
    280         uint32_t sz;
    281         uint32_t i;
    282 
    283258        /* 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(
    288260            bg_ref->block_group, bg_ref->fs->superblock);
    289261       
     
    297269       
    298270        /* 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);
    300272        memset(bitmap, 0, block_size);
    301273       
    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       
    305282        /* 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)
    307284                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       
    335286        bitmap_block->dirty = true;
    336287       
     
    469420        }
    470421       
    471         /* Initialize in-memory representation */
     422        /* Inititialize in-memory representation */
    472423        newref->block_group = newref->block->data + offset;
    473424        newref->fs = fs;
     
    534485        /* If checksum not supported, 0 will be returned */
    535486        uint16_t crc = 0;
    536 
     487       
    537488        /* Compute the checksum only if the filesystem supports it */
    538489        if (ext4_superblock_has_feature_read_only(sb,
     
    547498               
    548499                /* Initialization */
    549                 crc = crc16_ibm(~0, sb->uuid, sizeof(sb->uuid));
     500                crc = crc16(~0, sb->uuid, sizeof(sb->uuid));
    550501               
    551502                /* 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));
    553504               
    554505                /* 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);
    556507               
    557508                /* Skip checksum */
     
    562513                    EXT4_FEATURE_INCOMPAT_64BIT)) &&
    563514                    (offset < ext4_superblock_get_desc_size(sb)))
    564                         crc = crc16_ibm(crc, ((uint8_t *) bg) + offset,
     515                        crc = crc16(crc, ((uint8_t *) bg) + offset,
    565516                            ext4_superblock_get_desc_size(sb) - offset);
    566517        }
     
    569520}
    570521
    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 
    694522/** Put reference to block group.
    695523 *
    696  * @param ref Pointer for reference to be put back
     524 * @oaram ref Pointer for reference to be put back
    697525 *
    698526 * @return Error code
     
    968796                }
    969797               
    970                 rc = block_put(block);
    971                 if (rc != EOK)
    972                         return rc;
    973 
     798                block_put(block);
    974799                rc = ext4_balloc_free_block(inode_ref, fblock);
    975800                if (rc != EOK)
     
    1015840                                }
    1016841                               
    1017                                 rc = block_put(subblock);
    1018                                 if (rc != EOK) {
    1019                                         block_put(block);
    1020                                         return rc;
    1021                                 }
     842                                block_put(subblock);
    1022843                        }
    1023844                       
     
    1029850                }
    1030851               
    1031                 rc = block_put(block);
    1032                 if (rc != EOK)
    1033                         return rc;
    1034 
     852                block_put(block);
    1035853                rc = ext4_balloc_free_block(inode_ref, fblock);
    1036854                if (rc != EOK)
Note: See TracChangeset for help on using the changeset viewer.