Changeset ad34feb in mainline for uspace/lib/ext2


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

Location:
uspace/lib/ext2
Files:
4 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 *
  • uspace/lib/ext2/libext2_filesystem.h

    ra54af66 rad34feb  
    6060    ext2_inode_ref_t **);
    6161extern int ext2_filesystem_put_inode_ref(ext2_inode_ref_t *);
     62extern int ext2_filesystem_get_inode_data_block_index(ext2_filesystem_t *, ext2_inode_t*,
     63    aoff64_t, uint32_t*);
    6264extern void ext2_filesystem_fini(ext2_filesystem_t *);
    6365
  • uspace/lib/ext2/libext2_inode.c

    ra54af66 rad34feb  
    3838#include "libext2_superblock.h"
    3939#include <byteorder.h>
     40#include <assert.h>
    4041
    4142/**
     
    142143
    143144/**
     145 * Get number of blocks allocated for contents of the file
     146 * represented by this inode.
     147 *
     148 * @param inode pointer to inode
     149 */
     150inline uint32_t ext2_inode_get_reserved_blocks(ext2_superblock_t *sb,
     151    ext2_inode_t *inode)
     152{
     153        return ext2_inode_get_reserved_512_blocks(inode) /
     154            (ext2_superblock_get_block_size(sb) / 512);
     155}
     156
     157/**
    144158 * Get inode flags
    145159 *
     
    158172inline uint32_t ext2_inode_get_direct_block(ext2_inode_t *inode, uint8_t idx)
    159173{
     174        assert(idx < EXT2_INODE_DIRECT_BLOCKS);
    160175        return uint32_t_le2host(inode->direct_blocks[idx]);
    161176}
     
    165180 *
    166181 * @param inode pointer to inode
     182 * @param idx Indirection level. Valid values are 0 <= idx < 3, where 0 is
     183 *            singly-indirect block and 2 is triply-indirect-block
    167184 */
    168 inline uint32_t ext2_inode_get_single_indirect_block(ext2_inode_t *inode)
     185inline uint32_t ext2_inode_get_indirect_block(ext2_inode_t *inode, uint8_t idx)
    169186{
    170         return uint32_t_le2host(inode->single_indirect_block);
     187        assert(idx < 3);
     188        return uint32_t_le2host(inode->indirect_blocks[idx]);
    171189}
    172 
    173 /**
    174  * Get double indirect block ID
    175  *
    176  * @param inode pointer to inode
    177  */
    178 inline uint32_t ext2_inode_get_double_indirect_block(ext2_inode_t *inode)
    179 {
    180         return uint32_t_le2host(inode->double_indirect_block);
    181 }
    182 
    183 /**
    184  * Get triple indirect block ID
    185  *
    186  * @param inode pointer to inode
    187  */
    188 inline uint32_t ext2_inode_get_triple_indirect_block(ext2_inode_t *inode)
    189 {
    190         return uint32_t_le2host(inode->triple_indirect_block);
    191 }
    192 
    193 
    194190
    195191/** @}
  • uspace/lib/ext2/libext2_inode.h

    ra54af66 rad34feb  
    5151        uint8_t unused2[4];
    5252        uint32_t direct_blocks[12]; // Direct block ids stored in this inode
    53         uint32_t single_indirect_block;
    54         uint32_t double_indirect_block;
    55         uint32_t triple_indirect_block;
     53        uint32_t indirect_blocks[3];
    5654        uint32_t version;
    5755        uint32_t file_acl;
     
    7573#define EXT2_INODE_MODE_ACCESS_MASK     0x0FFF
    7674#define EXT2_INODE_MODE_TYPE_MASK       0xF000
     75#define EXT2_INODE_DIRECT_BLOCKS        12
    7776
    7877typedef struct ext2_inode_ref {
     
    8887inline uint16_t ext2_inode_get_usage_count(ext2_inode_t *);
    8988inline uint32_t ext2_inode_get_reserved_512_blocks(ext2_inode_t *);
     89inline uint32_t ext2_inode_get_reserved_blocks(ext2_superblock_t *,
     90    ext2_inode_t *);
    9091inline uint32_t ext2_inode_get_flags(ext2_inode_t *);
    9192inline uint32_t ext2_inode_get_direct_block(ext2_inode_t *, uint8_t);
    92 inline uint32_t ext2_inode_get_single_indirect_block(ext2_inode_t *);
    93 inline uint32_t ext2_inode_get_double_indirect_block(ext2_inode_t *);
    94 inline uint32_t ext2_inode_get_triple_indirect_block(ext2_inode_t *);
     93inline uint32_t ext2_inode_get_indirect_block(ext2_inode_t *, uint8_t level);
    9594
    9695
Note: See TracChangeset for help on using the changeset viewer.