Changeset ad34feb in mainline for uspace/lib/ext2/libext2_filesystem.c


Ignore:
Timestamp:
2011-02-23T23:07:28Z (14 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
102d400
Parents:
a54af66
Message:

Implement reading of blocks from inode in libext2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/ext2/libext2_filesystem.c

    ra54af66 rad34feb  
    4141#include <libblock.h>
    4242#include <malloc.h>
     43#include <assert.h>
    4344
    4445/**
     
    255256
    256257/**
     258 * Find a filesystem block number where iblock-th data block
     259 * of the given inode is located.
     260 *
     261 * @return              EOK on success or negative error code on failure
     262 */
     263int ext2_filesystem_get_inode_data_block_index(ext2_filesystem_t *fs, ext2_inode_t* inode,
     264    aoff64_t iblock, uint32_t* fblock)
     265{
     266        int rc;
     267        aoff64_t limits[4];
     268        uint32_t block_ids_per_block;
     269        aoff64_t blocks_per_level[4];
     270        uint32_t offset_in_block;
     271        uint32_t current_block;
     272        aoff64_t block_offset_in_level;
     273        int i;
     274        int level;
     275        block_t *block;
     276       
     277        if (iblock < EXT2_INODE_DIRECT_BLOCKS) {
     278                current_block = ext2_inode_get_direct_block(inode, (uint32_t)iblock);
     279                if (current_block == 0) {
     280                        return EIO;
     281                }
     282                *fblock = current_block;
     283                return EOK;
     284        }
     285       
     286        // Compute limits for indirect block levels
     287        // TODO: compute this once when loading filesystem and store in ext2_filesystem_t
     288        block_ids_per_block = ext2_superblock_get_block_size(fs->superblock) / sizeof(uint32_t);
     289        limits[0] = EXT2_INODE_DIRECT_BLOCKS;
     290        blocks_per_level[0] = 1;
     291        for (i = 1; i < 4; i++) {
     292                blocks_per_level[i]  = blocks_per_level[i-1] *
     293                    block_ids_per_block;
     294                limits[i] = limits[i-1] + blocks_per_level[i];
     295        }
     296       
     297        // Determine the indirection level needed to get the desired block
     298        level = -1;
     299        for (i = 1; i < 4; i++) {
     300                if (iblock < limits[i]) {
     301                        level = i;
     302                        break;
     303                }
     304        }
     305       
     306        if (level == -1) {
     307                return EIO;
     308        }
     309       
     310        block_offset_in_level = iblock - limits[level-1];
     311        current_block = ext2_inode_get_indirect_block(inode, level-1);
     312        offset_in_block = block_offset_in_level / blocks_per_level[level-1];
     313       
     314        while (level > 0) {
     315                rc = block_get(&block, fs->device, current_block, 0);
     316                if (rc != EOK) {
     317                        return rc;
     318                }
     319               
     320                assert(offset_in_block < block_ids_per_block);
     321                current_block = ((uint32_t*)block->data)[offset_in_block];
     322               
     323                rc = block_put(block);
     324                if (rc != EOK) {
     325                        return rc;
     326                }
     327               
     328                if (current_block == 0) {
     329                        return EIO;
     330                }
     331               
     332                level -= 1;
     333               
     334                if (level == 0) {
     335                        break;
     336                }
     337               
     338                offset_in_block = block_offset_in_level / blocks_per_level[level-1];
     339                block_offset_in_level %= blocks_per_level[level-1];
     340        }
     341       
     342        *fblock = current_block;
     343       
     344        return EOK;
     345}
     346
     347/**
    257348 * Finalize an instance of filesystem
    258349 *
Note: See TracChangeset for help on using the changeset viewer.