Ignore:
Timestamp:
2011-10-06T09:48:53Z (13 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1114173
Parents:
3712434
Message:

mounting + list of mounted directory (ported from ext2) - many TODO remaining

File:
1 edited

Legend:

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

    r3712434 r9b9d37bb  
    3636 */
    3737
     38#include <byteorder.h>
    3839#include <errno.h>
    3940#include <malloc.h>
     
    144145    ext4_block_group_ref_t **ref)
    145146{
     147        EXT4FS_DBG("");
     148
    146149        int rc;
    147150        aoff64_t block_id;
     
    161164        block_id = ext4_superblock_get_first_data_block(fs->superblock) + 1;
    162165
     166        EXT4FS_DBG("block_size = \%d", ext4_superblock_get_block_size(fs->superblock));
     167        EXT4FS_DBG("descriptors_per_block = \%d", descriptors_per_block);
     168        EXT4FS_DBG("bgid = \%d", bgid);
     169        EXT4FS_DBG("first_data_block: \%d", (uint32_t)block_id);
     170
    163171        /* Find the block containing the descriptor we are looking for */
    164172        block_id += bgid / descriptors_per_block;
    165173        offset = (bgid % descriptors_per_block) * EXT4_BLOCK_GROUP_DESCRIPTOR_SIZE;
    166174
     175        EXT4FS_DBG("updated block_id: \%d", (uint32_t)block_id);
     176
    167177        rc = block_get(&newref->block, fs->device, block_id, 0);
    168178        if (rc != EOK) {
     179
     180                EXT4FS_DBG("block_get error: \%d", rc);
     181
    169182                free(newref);
    170183                return rc;
    171184        }
    172185
     186        EXT4FS_DBG("block read");
     187
    173188        newref->block_group = newref->block->data + offset;
    174189
    175190        *ref = newref;
     191
     192        EXT4FS_DBG("finished");
    176193
    177194        return EOK;
     
    184201    ext4_inode_ref_t **ref)
    185202{
     203        EXT4FS_DBG("");
     204
    186205        int rc;
    187206        aoff64_t block_id;
     
    202221        }
    203222
     223        EXT4FS_DBG("allocated");
     224
    204225        inodes_per_group = ext4_superblock_get_inodes_per_group(fs->superblock);
     226
     227        EXT4FS_DBG("inodes_per_group_loaded");
    205228
    206229        /* inode numbers are 1-based, but it is simpler to work with 0-based
     
    211234        offset_in_group = index % inodes_per_group;
    212235
     236        EXT4FS_DBG("index: \%d", index);
     237        EXT4FS_DBG("inodes_per_group: \%d", inodes_per_group);
     238        EXT4FS_DBG("bg_id: \%d", block_group);
     239
    213240        rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
    214241        if (rc != EOK) {
     
    216243                return rc;
    217244        }
     245
     246        EXT4FS_DBG("block_group_ref loaded");
    218247
    219248        inode_table_start = ext4_block_group_get_inode_table_first_block(
    220249            bg_ref->block_group);
    221250
     251        EXT4FS_DBG("inode_table block loaded");
     252
    222253        inode_size = ext4_superblock_get_inode_size(fs->superblock);
    223254        block_size = ext4_superblock_get_block_size(fs->superblock);
     
    228259        offset_in_block = byte_offset_in_group % block_size;
    229260
     261        EXT4FS_DBG("superblock info loaded");
     262
    230263        rc = block_get(&newref->block, fs->device, block_id, 0);
    231264        if (rc != EOK) {
     
    233266                return rc;
    234267        }
     268
     269        EXT4FS_DBG("block got");
    235270
    236271        newref->inode = newref->block->data + offset_in_block;
     
    242277        *ref = newref;
    243278
     279        EXT4FS_DBG("finished");
     280
     281        return EOK;
     282}
     283
     284int ext4_filesystem_put_inode_ref(ext4_inode_ref_t *ref)
     285{
     286        int rc;
     287
     288        rc = block_put(ref->block);
     289        free(ref);
     290
     291        return rc;
     292}
     293
     294int ext4_filesystem_get_inode_data_block_index(ext4_filesystem_t *fs, ext4_inode_t* inode,
     295    aoff64_t iblock, uint32_t* fblock)
     296{
     297        int rc;
     298        aoff64_t limits[4];
     299        uint32_t block_ids_per_block;
     300        aoff64_t blocks_per_level[4];
     301        uint32_t offset_in_block;
     302        uint32_t current_block;
     303        aoff64_t block_offset_in_level;
     304        int i;
     305        int level;
     306        block_t *block;
     307
     308        /* Handle simple case when we are dealing with direct reference */
     309        if (iblock < EXT4_INODE_DIRECT_BLOCKS) {
     310                current_block = ext4_inode_get_direct_block(inode, (uint32_t)iblock);
     311                *fblock = current_block;
     312                return EOK;
     313        }
     314
     315        /* Compute limits for indirect block levels
     316         * TODO: compute this once when loading filesystem and store in ext2_filesystem_t
     317         */
     318        block_ids_per_block = ext4_superblock_get_block_size(fs->superblock) / sizeof(uint32_t);
     319        limits[0] = EXT4_INODE_DIRECT_BLOCKS;
     320        blocks_per_level[0] = 1;
     321        for (i = 1; i < 4; i++) {
     322                blocks_per_level[i]  = blocks_per_level[i-1] *
     323                    block_ids_per_block;
     324                limits[i] = limits[i-1] + blocks_per_level[i];
     325        }
     326
     327        /* Determine the indirection level needed to get the desired block */
     328        level = -1;
     329        for (i = 1; i < 4; i++) {
     330                if (iblock < limits[i]) {
     331                        level = i;
     332                        break;
     333                }
     334        }
     335
     336        if (level == -1) {
     337                return EIO;
     338        }
     339
     340        /* Compute offsets for the topmost level */
     341        block_offset_in_level = iblock - limits[level-1];
     342        current_block = ext4_inode_get_indirect_block(inode, level-1);
     343        offset_in_block = block_offset_in_level / blocks_per_level[level-1];
     344
     345        /* Navigate through other levels, until we find the block number
     346         * or find null reference meaning we are dealing with sparse file
     347         */
     348        while (level > 0) {
     349                rc = block_get(&block, fs->device, current_block, 0);
     350                if (rc != EOK) {
     351                        return rc;
     352                }
     353
     354                assert(offset_in_block < block_ids_per_block);
     355                current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]);
     356
     357                rc = block_put(block);
     358                if (rc != EOK) {
     359                        return rc;
     360                }
     361
     362                if (current_block == 0) {
     363                        /* This is a sparse file */
     364                        *fblock = 0;
     365                        return EOK;
     366                }
     367
     368                level -= 1;
     369
     370                /* If we are on the last level, break here as
     371                 * there is no next level to visit
     372                 */
     373                if (level == 0) {
     374                        break;
     375                }
     376
     377                /* Visit the next level */
     378                block_offset_in_level %= blocks_per_level[level];
     379                offset_in_block = block_offset_in_level / blocks_per_level[level-1];
     380        }
     381
     382        *fblock = current_block;
     383
    244384        return EOK;
    245385}
Note: See TracChangeset for help on using the changeset viewer.