Changeset 38542dc in mainline for uspace/lib/ext4/libext4_extent.c


Ignore:
Timestamp:
2012-08-12T18:36:10Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
49505fe
Parents:
b08e7970
Message:

ext4 code review and coding style cleanup

File:
1 edited

Legend:

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

    rb08e7970 r38542dc  
    2929/** @addtogroup libext4
    3030 * @{
    31  */
    32 
     31 */
    3332/**
    34  * @file        libext4_extent.c
    35  * @brief       Ext4 extent structures operations.
     33 * @file  libext4_extent.c
     34 * @brief Ext4 extent structures operations.
    3635 */
    3736
     
    4342/** Get logical number of the block covered by extent.
    4443 *
    45  * @param extent        extent to load number from
    46  * @return                      logical number of the first block covered by extent
     44 * @param extent Extent to load number from
     45 *
     46 * @return Logical number of the first block covered by extent
     47 *
    4748 */
    4849uint32_t ext4_extent_get_first_block(ext4_extent_t *extent)
     
    5354/** Set logical number of the first block covered by extent.
    5455 *
    55  * @param extent        extent to set number to
    56  * @param iblock        logical number of the first block covered by extent
     56 * @param extent Extent to set number to
     57 * @param iblock Logical number of the first block covered by extent
     58 *
    5759 */
    5860void ext4_extent_set_first_block(ext4_extent_t *extent, uint32_t iblock)
     
    6365/** Get number of blocks covered by extent.
    6466 *
    65  * @param extent        extent to load count from
    66  * @return                      number of blocks covered by extent
     67 * @param extent Extent to load count from
     68 *
     69 * @return Number of blocks covered by extent
     70 *
    6771 */
    6872uint16_t ext4_extent_get_block_count(ext4_extent_t *extent)
     
    7377/** Set number of blocks covered by extent.
    7478 *
    75  * @param extent        extent to load count from
    76  * @param count         number of blocks covered by extent
     79 * @param extent Extent to load count from
     80 * @param count  Number of blocks covered by extent
     81 *
    7782 */
    7883void ext4_extent_set_block_count(ext4_extent_t *extent, uint16_t count)
     
    8388/** Get physical number of the first block covered by extent.
    8489 *
    85  * @param extent        extent to load number
    86  * @return                      physical number of the first block covered by extent
     90 * @param extent Extent to load number
     91 *
     92 * @return Physical number of the first block covered by extent
     93 *
    8794 */
    8895uint64_t ext4_extent_get_start(ext4_extent_t *extent)
    8996{
    9097        return ((uint64_t)uint16_t_le2host(extent->start_hi)) << 32 |
    91                         ((uint64_t)uint32_t_le2host(extent->start_lo));
     98            ((uint64_t)uint32_t_le2host(extent->start_lo));
    9299}
    93100
    94101/** Set physical number of the first block covered by extent.
    95102 *
    96  * @param extent        extent to load number
    97  * @param fblock        physical number of the first block covered by extent
     103 * @param extent Extent to load number
     104 * @param fblock Physical number of the first block covered by extent
     105 *
    98106 */
    99107void ext4_extent_set_start(ext4_extent_t *extent, uint64_t fblock)
     
    105113/** Get logical number of the block covered by extent index.
    106114 *
    107  * @param index         extent index to load number from
    108  * @return                      logical number of the first block covered by extent index
     115 * @param index Extent index to load number from
     116 *
     117 * @return Logical number of the first block covered by extent index
     118 *
    109119 */
    110120uint32_t ext4_extent_index_get_first_block(ext4_extent_index_t *index)
     
    115125/** Set logical number of the block covered by extent index.
    116126 *
    117  * @param index         extent index to set number to
    118  * @param iblock        logical number of the first block covered by extent index
     127 * @param index  Extent index to set number to
     128 * @param iblock Logical number of the first block covered by extent index
     129 *
    119130 */
    120131void ext4_extent_index_set_first_block(ext4_extent_index_t *index,
    121                 uint32_t iblock)
     132    uint32_t iblock)
    122133{
    123134        index->first_block = host2uint32_t_le(iblock);
     
    126137/** Get physical number of block where the child node is located.
    127138 *
    128  * @param index         extent index to load number from
    129  * @return                      physical number of the block with child node
     139 * @param index Extent index to load number from
     140 *
     141 * @return Physical number of the block with child node
     142 *
    130143 */
    131144uint64_t ext4_extent_index_get_leaf(ext4_extent_index_t *index)
    132145{
    133         return ((uint64_t)uint16_t_le2host(index->leaf_hi)) << 32 |
    134                 ((uint64_t)uint32_t_le2host(index->leaf_lo));
     146        return ((uint64_t) uint16_t_le2host(index->leaf_hi)) << 32 |
     147            ((uint64_t)uint32_t_le2host(index->leaf_lo));
    135148}
    136149
    137150/** Set physical number of block where the child node is located.
    138151 *
    139  * @param index         extent index to set number to
    140  * @param fblock        physical number of the block with child node
     152 * @param index  Extent index to set number to
     153 * @param fblock Ohysical number of the block with child node
     154 *
    141155 */
    142156void ext4_extent_index_set_leaf(ext4_extent_index_t *index, uint64_t fblock)
    143157{
    144158        index->leaf_lo = host2uint32_t_le((fblock << 32) >> 32);
    145         index->leaf_hi = host2uint16_t_le((uint16_t)(fblock >> 32));
     159        index->leaf_hi = host2uint16_t_le((uint16_t) (fblock >> 32));
    146160}
    147161
    148162/** Get magic value from extent header.
    149163 *
    150  * @param header        extent header to load value from
    151  * @return                      magic value of extent header
     164 * @param header Extent header to load value from
     165 *
     166 * @return Magic value of extent header
     167 *
    152168 */
    153169uint16_t ext4_extent_header_get_magic(ext4_extent_header_t *header)
     
    158174/** Set magic value to extent header.
    159175 *
    160  * @param header        extent header to set value to
    161  * @param magic         magic value of extent header
     176 * @param header Extent header to set value to
     177 * @param magic  Magic value of extent header
     178 *
    162179 */
    163180void ext4_extent_header_set_magic(ext4_extent_header_t *header, uint16_t magic)
     
    168185/** Get number of entries from extent header
    169186 *
    170  * @param header        extent header to get value from
    171  * @return                      number of entries covered by extent header
     187 * @param header Extent header to get value from
     188 *
     189 * @return Number of entries covered by extent header
     190 *
    172191 */
    173192uint16_t ext4_extent_header_get_entries_count(ext4_extent_header_t *header)
     
    178197/** Set number of entries to extent header
    179198 *
    180  * @param header        extent header to set value to
    181  * @param count         number of entries covered by extent header
     199 * @param header Extent header to set value to
     200 * @param count  Number of entries covered by extent header
     201 *
    182202 */
    183203void ext4_extent_header_set_entries_count(ext4_extent_header_t *header,
    184                 uint16_t count)
     204    uint16_t count)
    185205{
    186206        header->entries_count = host2uint16_t_le(count);
     
    189209/** Get maximum number of entries from extent header
    190210 *
    191  * @param header        extent header to get value from
    192  * @return                      maximum number of entries covered by extent header
     211 * @param header Extent header to get value from
     212 *
     213 * @return Maximum number of entries covered by extent header
     214 *
    193215 */
    194216uint16_t ext4_extent_header_get_max_entries_count(ext4_extent_header_t *header)
     
    199221/** Set maximum number of entries to extent header
    200222 *
    201  * @param header        extent header to set value to
    202  * @param max_count maximum number of entries covered by extent header
     223 * @param header    Extent header to set value to
     224 * @param max_count Maximum number of entries covered by extent header
     225 *
    203226 */
    204227void ext4_extent_header_set_max_entries_count(ext4_extent_header_t *header,
    205                 uint16_t max_count)
     228    uint16_t max_count)
    206229{
    207230        header->max_entries_count = host2uint16_t_le(max_count);
     
    210233/** Get depth of extent subtree.
    211234 *
    212  * @param header        extent header to get value from
    213  * @return                      depth of extent subtree
     235 * @param header Extent header to get value from
     236 *
     237 * @return Depth of extent subtree
     238 *
    214239 */
    215240uint16_t ext4_extent_header_get_depth(ext4_extent_header_t *header)
     
    220245/** Set depth of extent subtree.
    221246 *
    222  * @param header        extent header to set value to
    223  * @param depth         depth of extent subtree
     247 * @param header Extent header to set value to
     248 * @param depth  Depth of extent subtree
     249 *
    224250 */
    225251void ext4_extent_header_set_depth(ext4_extent_header_t *header, uint16_t depth)
     
    230256/** Get generation from extent header
    231257 *
    232  * @param header        extent header to get value from
    233  * @return                      generation
     258 * @param header Extent header to get value from
     259 *
     260 * @return Generation
     261 *
    234262 */
    235263uint32_t ext4_extent_header_get_generation(ext4_extent_header_t *header)
     
    240268/** Set generation to extent header
    241269 *
    242  * @param header                extent header to set value to
    243  * @param generation    generation
     270 * @param header     Extent header to set value to
     271 * @param generation Generation
     272 *
    244273 */
    245274void ext4_extent_header_set_generation(ext4_extent_header_t *header,
    246                 uint32_t generation)
     275    uint32_t generation)
    247276{
    248277        header->generation = host2uint32_t_le(generation);
     
    251280/** Binary search in extent index node.
    252281 *
    253  * @param header        extent header of index node
    254  * @param index         output value - found index will be set here
    255  * @param iblock        logical block number to find in index node
     282 * @param header Extent header of index node
     283 * @param index  Output value - found index will be set here
     284 * @param iblock Logical block number to find in index node
     285 *
    256286 */
    257287static void ext4_extent_binsearch_idx(ext4_extent_header_t *header,
    258         ext4_extent_index_t **index, uint32_t iblock)
    259 {
    260         ext4_extent_index_t *r, *l, *m;
    261 
    262         uint16_t entries_count = ext4_extent_header_get_entries_count(header);
    263 
     288    ext4_extent_index_t **index, uint32_t iblock)
     289{
     290        ext4_extent_index_t *r;
     291        ext4_extent_index_t *l;
     292        ext4_extent_index_t *m;
     293       
     294        uint16_t entries_count =
     295            ext4_extent_header_get_entries_count(header);
     296       
    264297        /* Initialize bounds */
    265298        l = EXT4_EXTENT_FIRST_INDEX(header) + 1;
    266299        r = EXT4_EXTENT_FIRST_INDEX(header) + entries_count - 1;
    267 
     300       
    268301        /* Do binary search */
    269302        while (l <= r) {
    270303                m = l + (r - l) / 2;
    271304                uint32_t first_block = ext4_extent_index_get_first_block(m);
    272                 if (iblock < first_block) {
    273                                 r = m - 1;
    274                 } else {
    275                                 l = m + 1;
    276                 }
    277         }
    278 
     305               
     306                if (iblock < first_block)
     307                        r = m - 1;
     308                else
     309                        l = m + 1;
     310        }
     311       
    279312        /* Set output value */
    280313        *index = l - 1;
     
    282315
    283316/** Binary search in extent leaf node.
    284  * @param header        extent header of leaf node
    285  * @param extent        output value - found extent will be set here,
    286  *                                      or NULL if node is empty
    287  * @param iblock        logical block number to find in leaf node
     317 *
     318 * @param header Extent header of leaf node
     319 * @param extent Output value - found extent will be set here,
     320 *               or NULL if node is empty
     321 * @param iblock Logical block number to find in leaf node
    288322 *
    289323 */
    290324static void ext4_extent_binsearch(ext4_extent_header_t *header,
    291                 ext4_extent_t **extent, uint32_t iblock)
    292 {
    293         ext4_extent_t *r, *l, *m;
    294 
    295         uint16_t entries_count = ext4_extent_header_get_entries_count(header);
    296 
     325    ext4_extent_t **extent, uint32_t iblock)
     326{
     327        ext4_extent_t *r;
     328        ext4_extent_t *l;
     329        ext4_extent_t *m;
     330       
     331        uint16_t entries_count =
     332            ext4_extent_header_get_entries_count(header);
     333       
    297334        if (entries_count == 0) {
    298335                /* this leaf is empty */
     
    300337                return;
    301338        }
    302 
     339       
    303340        /* Initialize bounds */
    304341        l = EXT4_EXTENT_FIRST(header) + 1;
    305342        r = EXT4_EXTENT_FIRST(header) + entries_count - 1;
    306 
     343       
    307344        /* Do binary search */
    308345        while (l <= r) {
    309346                m = l + (r - l) / 2;
    310347                uint32_t first_block = ext4_extent_get_first_block(m);
    311                 if (iblock < first_block) {
    312                                 r = m - 1;
    313                 } else {
    314                                 l = m + 1;
    315                 }
    316         }
    317 
     348               
     349                if (iblock < first_block)
     350                        r = m - 1;
     351                else
     352                        l = m + 1;
     353        }
     354       
    318355        /* Set output value */
    319356        *extent = l - 1;
     
    324361 * There is no need to save path in the tree during this algorithm.
    325362 *
    326  * @param inode_ref             i-node to load block from
    327  * @param iblock                logical block number to find
    328  * @param fblock                output value for physical block number
    329  * @return                              error code
    330  */
    331 int ext4_extent_find_block(ext4_inode_ref_t *inode_ref,
    332                 uint32_t iblock, uint32_t *fblock)
    333 {
    334         int rc;
    335 
     363 * @param inode_ref I-node to load block from
     364 * @param iblock    Logical block number to find
     365 * @param fblock    Output value for physical block number
     366 *
     367 * @return Error code
     368 *
     369 */
     370int ext4_extent_find_block(ext4_inode_ref_t *inode_ref, uint32_t iblock,
     371    uint32_t *fblock)
     372{
    336373        /* Compute bound defined by i-node size */
    337         uint64_t inode_size = ext4_inode_get_size(
    338                         inode_ref->fs->superblock, inode_ref->inode);
    339 
    340         uint32_t block_size = ext4_superblock_get_block_size(
    341                         inode_ref->fs->superblock);
    342 
     374        uint64_t inode_size =
     375            ext4_inode_get_size(inode_ref->fs->superblock, inode_ref->inode);
     376       
     377        uint32_t block_size =
     378            ext4_superblock_get_block_size(inode_ref->fs->superblock);
     379       
    343380        uint32_t last_idx = (inode_size - 1) / block_size;
    344 
     381       
    345382        /* Check if requested iblock is not over size of i-node */
    346383        if (iblock > last_idx) {
     
    348385                return EOK;
    349386        }
    350 
    351         block_t* block = NULL;
    352 
     387       
     388        block_t *block = NULL;
     389       
    353390        /* Walk through extent tree */
    354         ext4_extent_header_t *header = ext4_inode_get_extent_header(inode_ref->inode);
    355 
     391        ext4_extent_header_t *header =
     392            ext4_inode_get_extent_header(inode_ref->inode);
     393       
    356394        while (ext4_extent_header_get_depth(header) != 0) {
    357 
    358395                /* Search index in node */
    359396                ext4_extent_index_t *index;
    360397                ext4_extent_binsearch_idx(header, &index, iblock);
    361 
     398               
    362399                /* Load child node and set values for the next iteration */
    363400                uint64_t child = ext4_extent_index_get_leaf(index);
    364 
    365                 if (block != NULL) {
     401               
     402                if (block != NULL)
    366403                        block_put(block);
    367                 }
    368 
    369                 rc = block_get(&block, inode_ref->fs->device, child, BLOCK_FLAGS_NONE);
    370                 if (rc != EOK) {
     404               
     405                int rc = block_get(&block, inode_ref->fs->device, child,
     406                    BLOCK_FLAGS_NONE);
     407                if (rc != EOK)
    371408                        return rc;
    372                 }
    373 
     409               
    374410                header = (ext4_extent_header_t *)block->data;
    375411        }
    376 
     412       
    377413        /* Search extent in the leaf block */
    378414        ext4_extent_t* extent = NULL;
    379415        ext4_extent_binsearch(header, &extent, iblock);
    380 
     416       
    381417        /* Prevent empty leaf */
    382418        if (extent == NULL) {
    383419                *fblock = 0;
    384420        } else {
    385 
    386421                /* Compute requested physical block address */
    387422                uint32_t phys_block;
    388423                uint32_t first = ext4_extent_get_first_block(extent);
    389424                phys_block = ext4_extent_get_start(extent) + iblock - first;
    390 
     425               
    391426                *fblock = phys_block;
    392427        }
    393 
     428       
    394429        /* Cleanup */
    395         if (block != NULL) {
     430        if (block != NULL)
    396431                block_put(block);
    397         }
    398 
     432       
    399433        return EOK;
    400434}
    401 
    402435
    403436/** Find extent for specified iblock.
     
    406439 * saving the path through the tree for possible future modifications.
    407440 *
    408  * @param inode_ref             i-node to read extent tree from
    409  * @param iblock                iblock to find extent for
    410  * @param ret_path              output value for loaded path from extent tree
    411  * @return                              error code
    412  */
    413 static int ext4_extent_find_extent(ext4_inode_ref_t *inode_ref,
    414                 uint32_t iblock, ext4_extent_path_t **ret_path)
    415 {
    416         int rc;
    417 
     441 * @param inode_ref I-node to read extent tree from
     442 * @param iblock    Iblock to find extent for
     443 * @param ret_path  Output value for loaded path from extent tree
     444 *
     445 * @return Error code
     446 *
     447 */
     448static int ext4_extent_find_extent(ext4_inode_ref_t *inode_ref, uint32_t iblock,
     449    ext4_extent_path_t **ret_path)
     450{
    418451        ext4_extent_header_t *eh =
    419                         ext4_inode_get_extent_header(inode_ref->inode);
    420 
     452            ext4_inode_get_extent_header(inode_ref->inode);
     453       
    421454        uint16_t depth = ext4_extent_header_get_depth(eh);
    422 
     455       
    423456        ext4_extent_path_t *tmp_path;
    424 
     457       
    425458        /* Added 2 for possible tree growing */
    426459        tmp_path = malloc(sizeof(ext4_extent_path_t) * (depth + 2));
    427         if (tmp_path == NULL) {
     460        if (tmp_path == NULL)
    428461                return ENOMEM;
    429         }
    430 
     462       
    431463        /* Initialize structure for algorithm start */
    432464        tmp_path[0].block = inode_ref->block;
    433465        tmp_path[0].header = eh;
    434 
     466       
    435467        /* Walk through the extent tree */
    436468        uint16_t pos = 0;
     469        int rc;
    437470        while (ext4_extent_header_get_depth(eh) != 0) {
    438 
    439471                /* Search index in index node by iblock */
    440                 ext4_extent_binsearch_idx(tmp_path[pos].header, &tmp_path[pos].index, iblock);
    441 
     472                ext4_extent_binsearch_idx(tmp_path[pos].header,
     473                    &tmp_path[pos].index, iblock);
     474               
    442475                tmp_path[pos].depth = depth;
    443476                tmp_path[pos].extent = NULL;
    444 
     477               
    445478                assert(tmp_path[pos].index != NULL);
    446 
     479               
    447480                /* Load information for the next iteration */
    448481                uint64_t fblock = ext4_extent_index_get_leaf(tmp_path[pos].index);
    449 
     482               
    450483                block_t *block;
    451                 rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NONE);
    452                 if (rc != EOK) {
     484                rc = block_get(&block, inode_ref->fs->device, fblock,
     485                    BLOCK_FLAGS_NONE);
     486                if (rc != EOK)
    453487                        goto cleanup;
    454                 }
    455 
     488               
    456489                pos++;
    457 
     490               
    458491                eh = (ext4_extent_header_t *)block->data;
    459492                tmp_path[pos].block = block;
    460493                tmp_path[pos].header = eh;
    461 
    462         }
    463 
     494        }
     495       
    464496        tmp_path[pos].depth = 0;
    465497        tmp_path[pos].extent = NULL;
    466498        tmp_path[pos].index = NULL;
    467 
    468     /* Find extent in the leaf node */
     499       
     500        /* Find extent in the leaf node */
    469501        ext4_extent_binsearch(tmp_path[pos].header, &tmp_path[pos].extent, iblock);
    470 
    471502        *ret_path = tmp_path;
    472 
     503       
    473504        return EOK;
    474 
     505       
    475506cleanup:
    476         /* Put loaded blocks
     507        /*
     508         * Put loaded blocks
    477509         * From 1: 0 is a block with inode data
    478510         */
    479511        for (uint16_t i = 1; i < tmp_path->depth; ++i) {
    480                 if (tmp_path[i].block) {
     512                if (tmp_path[i].block)
    481513                        block_put(tmp_path[i].block);
    482                 }
    483         }
    484 
     514        }
     515       
    485516        /* Destroy temporary data structure */
    486517        free(tmp_path);
    487 
     518       
    488519        return rc;
    489520}
     
    491522/** Release extent and all data blocks covered by the extent.
    492523 *
    493  * @param inode_ref             i-node to release extent and block from
    494  * @param extent                extent to release
    495  * @return                              error code
    496  */
    497 static int ext4_extent_release(
    498                 ext4_inode_ref_t *inode_ref, ext4_extent_t *extent)
    499 {
    500         int rc;
    501 
     524 * @param inode_ref I-node to release extent and block from
     525 * @param extent    Extent to release
     526 *
     527 * @return Error code
     528 *
     529 */
     530static int ext4_extent_release(ext4_inode_ref_t *inode_ref,
     531    ext4_extent_t *extent)
     532{
    502533        /* Compute number of the first physical block to release */
    503534        uint64_t start = ext4_extent_get_start(extent);
    504535        uint16_t block_count = ext4_extent_get_block_count(extent);
    505 
    506         rc = ext4_balloc_free_blocks(inode_ref, start, block_count);
    507         if (rc != EOK) {
    508                 return rc;
    509         }
    510 
    511         return EOK;
     536       
     537        return ext4_balloc_free_blocks(inode_ref, start, block_count);
    512538}
    513539
     
    517543 * the node. In the leaf node all extents will be released.
    518544 *
    519  * @param inode_ref             i-node where the branch is released
    520  * @param index                 index in the non-leaf node to be released
    521  *                                              with the whole subtree
    522  * @return                              error code
     545 * @param inode_ref I-node where the branch is released
     546 * @param index     Index in the non-leaf node to be released
     547 *                  with the whole subtree
     548 *
     549 * @return Error code
     550 *
    523551 */
    524552static int ext4_extent_release_branch(ext4_inode_ref_t *inode_ref,
    525553                ext4_extent_index_t *index)
    526554{
    527         int rc;
    528 
     555        uint32_t fblock = ext4_extent_index_get_leaf(index);
     556       
    529557        block_t* block;
    530 
    531         uint32_t fblock = ext4_extent_index_get_leaf(index);
    532 
    533         rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NONE);
    534         if (rc != EOK) {
     558        int rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NONE);
     559        if (rc != EOK)
    535560                return rc;
    536         }
    537 
     561       
    538562        ext4_extent_header_t *header = block->data;
    539 
     563       
    540564        if (ext4_extent_header_get_depth(header)) {
    541 
    542565                /* The node is non-leaf, do recursion */
    543 
    544566                ext4_extent_index_t *idx = EXT4_EXTENT_FIRST_INDEX(header);
    545 
     567               
    546568                /* Release all subbranches */
    547                 for (uint32_t i = 0; i < ext4_extent_header_get_entries_count(header); ++i, ++idx) {
     569                for (uint32_t i = 0;
     570                    i < ext4_extent_header_get_entries_count(header);
     571                    ++i, ++idx) {
    548572                        rc = ext4_extent_release_branch(inode_ref, idx);
    549                         if (rc != EOK) {
     573                        if (rc != EOK)
    550574                                return rc;
    551                         }
    552575                }
    553576        } else {
    554 
    555577                /* Leaf node reached */
    556578                ext4_extent_t *ext = EXT4_EXTENT_FIRST(header);
    557 
     579               
    558580                /* Release all extents and stop recursion */
    559 
    560                 for (uint32_t i = 0; i < ext4_extent_header_get_entries_count(header); ++i, ++ext) {
     581                for (uint32_t i = 0;
     582                    i < ext4_extent_header_get_entries_count(header);
     583                    ++i, ++ext) {
    561584                        rc = ext4_extent_release(inode_ref, ext);
    562                         if (rc != EOK) {
     585                        if (rc != EOK)
    563586                                return rc;
    564                         }
    565587                }
    566588        }
    567 
     589       
    568590        /* Release data block where the node was stored */
    569 
     591       
    570592        rc = block_put(block);
    571         if (rc != EOK) {
     593        if (rc != EOK)
    572594                return rc;
    573         }
    574 
     595       
    575596        ext4_balloc_free_block(inode_ref, fblock);
    576 
     597       
    577598        return EOK;
    578599}
     
    580601/** Release all data blocks starting from specified logical block.
    581602 *
    582  * @param inode_ref             i-node to release blocks from
    583  * @param iblock_from   first logical block to release
     603 * @param inode_ref   I-node to release blocks from
     604 * @param iblock_from First logical block to release
     605 *
    584606 */
    585607int ext4_extent_release_blocks_from(ext4_inode_ref_t *inode_ref,
    586                 uint32_t iblock_from)
    587 {
    588         int rc = EOK;
    589 
     608    uint32_t iblock_from)
     609{
    590610        /* Find the first extent to modify */
    591611        ext4_extent_path_t *path;
    592         rc = ext4_extent_find_extent(inode_ref, iblock_from, &path);
    593         if (rc != EOK) {
     612        int rc = ext4_extent_find_extent(inode_ref, iblock_from, &path);
     613        if (rc != EOK)
    594614                return rc;
    595         }
    596 
     615       
    597616        /* Jump to last item of the path (extent) */
    598617        ext4_extent_path_t *path_ptr = path;
    599         while (path_ptr->depth != 0) {
     618        while (path_ptr->depth != 0)
    600619                path_ptr++;
    601         }
    602 
     620       
    603621        assert(path_ptr->extent != NULL);
    604 
     622       
    605623        /* First extent maybe released partially */
    606         uint32_t first_iblock = ext4_extent_get_first_block(path_ptr->extent);
    607         uint32_t first_fblock = ext4_extent_get_start(path_ptr->extent) + iblock_from - first_iblock;
    608 
    609 
     624        uint32_t first_iblock =
     625            ext4_extent_get_first_block(path_ptr->extent);
     626        uint32_t first_fblock =
     627            ext4_extent_get_start(path_ptr->extent) + iblock_from - first_iblock;
     628       
    610629        uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);
    611 
    612         uint16_t delete_count = block_count - (
    613                         ext4_extent_get_start(path_ptr->extent) - first_fblock);
    614 
     630       
     631        uint16_t delete_count = block_count -
     632            (ext4_extent_get_start(path_ptr->extent) - first_fblock);
     633       
    615634        /* Release all blocks */
    616635        rc = ext4_balloc_free_blocks(inode_ref, first_fblock, delete_count);
    617         if (rc != EOK) {
     636        if (rc != EOK)
    618637                goto cleanup;
    619         }
    620 
     638       
    621639        /* Correct counter */
    622640        block_count -= delete_count;
    623641        ext4_extent_set_block_count(path_ptr->extent, block_count);
    624 
     642       
    625643        /* Initialize the following loop */
    626         uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header);
     644        uint16_t entries =
     645            ext4_extent_header_get_entries_count(path_ptr->header);
    627646        ext4_extent_t *tmp_ext = path_ptr->extent + 1;
    628647        ext4_extent_t *stop_ext = EXT4_EXTENT_FIRST(path_ptr->header) + entries;
    629 
     648       
    630649        /* If first extent empty, release it */
    631         if (block_count == 0) {
     650        if (block_count == 0)
    632651                entries--;
    633         }
    634 
     652       
    635653        /* Release all successors of the first extent in the same node */
    636654        while (tmp_ext < stop_ext) {
    637655                first_fblock = ext4_extent_get_start(tmp_ext);
    638656                delete_count = ext4_extent_get_block_count(tmp_ext);
    639 
     657               
    640658                rc = ext4_balloc_free_blocks(inode_ref, first_fblock, delete_count);
    641                 if (rc != EOK) {
     659                if (rc != EOK)
    642660                        goto cleanup;
    643                 }
    644 
     661               
    645662                entries--;
    646663                tmp_ext++;
    647664        }
    648 
     665       
    649666        ext4_extent_header_set_entries_count(path_ptr->header, entries);
    650667        path_ptr->block->dirty = true;
    651 
     668       
    652669        /* If leaf node is empty, parent entry must be modified */
    653670        bool remove_parent_record = false;
    654 
     671       
    655672        /* Don't release root block (including inode data) !!! */
    656673        if ((path_ptr != path) && (entries == 0)) {
    657674                rc = ext4_balloc_free_block(inode_ref, path_ptr->block->lba);
    658                 if (rc != EOK) {
     675                if (rc != EOK)
    659676                        goto cleanup;
    660                 }
     677               
    661678                remove_parent_record = true;
    662679        }
    663 
     680       
    664681        /* Jump to the parent */
    665682        --path_ptr;
    666 
     683       
    667684        /* Release all successors in all tree levels */
    668685        while (path_ptr >= path) {
     
    670687                ext4_extent_index_t *index = path_ptr->index + 1;
    671688                ext4_extent_index_t *stop =
    672                                 EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries;
    673 
     689                    EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries;
     690               
    674691                /* Correct entries count because of changes in the previous iteration */
    675                 if (remove_parent_record) {
     692                if (remove_parent_record)
    676693                        entries--;
    677                 }
    678 
     694               
    679695                /* Iterate over all entries and release the whole subtrees */
    680696                while (index < stop) {
    681697                        rc = ext4_extent_release_branch(inode_ref, index);
    682                         if (rc != EOK) {
     698                        if (rc != EOK)
    683699                                goto cleanup;
    684                         }
     700                       
    685701                        ++index;
    686702                        --entries;
    687703                }
    688 
     704               
    689705                ext4_extent_header_set_entries_count(path_ptr->header, entries);
    690706                path_ptr->block->dirty = true;
    691 
     707               
    692708                /* Free the node if it is empty */
    693709                if ((entries == 0) && (path_ptr != path)) {
    694710                        rc = ext4_balloc_free_block(inode_ref, path_ptr->block->lba);
    695                         if (rc != EOK) {
     711                        if (rc != EOK)
    696712                                goto cleanup;
    697                         }
    698 
     713                       
    699714                        /* Mark parent to be checked */
    700715                        remove_parent_record = true;
    701                 } else {
     716                } else
    702717                        remove_parent_record = false;
    703                 }
    704 
     718               
    705719                --path_ptr;
    706720        }
    707 
    708 
     721       
    709722cleanup:
    710         /* Put loaded blocks
     723        /*
     724         * Put loaded blocks
    711725         * starting from 1: 0 is a block with inode data
    712726         */
    713727        for (uint16_t i = 1; i <= path->depth; ++i) {
    714                 if (path[i].block) {
     728                if (path[i].block)
    715729                        block_put(path[i].block);
    716                 }
    717         }
    718 
     730        }
     731       
    719732        /* Destroy temporary data structure */
    720733        free(path);
    721 
     734       
    722735        return rc;
    723736}
    724737
    725 
    726738/** Append new extent to the i-node and do some splitting if necessary.
    727739 *
    728  * @param inode_ref                     i-node to append extent to
    729  * @param path                          path in the extent tree for possible splitting
    730  * @param last_path_item        input/output parameter for pointer to the last
    731  *                                                      valid item in the extent tree path
    732  * @param iblock                        logical index of block to append extent for
    733  * @return                                      error code
     740 * @param inode_ref      I-node to append extent to
     741 * @param path           Path in the extent tree for possible splitting
     742 * @param last_path_item Input/output parameter for pointer to the last
     743 *                       valid item in the extent tree path
     744 * @param iblock         Logical index of block to append extent for
     745 *
     746 * @return Error code
     747 *
    734748 */
    735749static int ext4_extent_append_extent(ext4_inode_ref_t *inode_ref,
    736                 ext4_extent_path_t *path, uint32_t iblock)
    737 {
    738         int rc;
    739 
     750    ext4_extent_path_t *path, uint32_t iblock)
     751{
    740752        ext4_extent_path_t *path_ptr = path + path->depth;
    741 
     753       
    742754        uint32_t block_size =
    743                         ext4_superblock_get_block_size(inode_ref->fs->superblock);
    744 
     755            ext4_superblock_get_block_size(inode_ref->fs->superblock);
     756       
    745757        /* Start splitting */
    746758        while (path_ptr > path) {
    747 
    748                 uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header);
    749                 uint16_t limit = ext4_extent_header_get_max_entries_count(path_ptr->header);
    750 
     759                uint16_t entries =
     760                    ext4_extent_header_get_entries_count(path_ptr->header);
     761                uint16_t limit =
     762                    ext4_extent_header_get_max_entries_count(path_ptr->header);
     763               
    751764                if (entries == limit) {
    752 
    753765                        /* Full node - allocate block for new one */
    754766                        uint32_t fblock;
    755                         rc = ext4_balloc_alloc_block(inode_ref, &fblock);
    756                         if (rc != EOK) {
     767                        int rc = ext4_balloc_alloc_block(inode_ref, &fblock);
     768                        if (rc != EOK)
    757769                                return rc;
    758                         }
    759 
     770                       
    760771                        block_t *block;
    761                         rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NOREAD);
     772                        rc = block_get(&block, inode_ref->fs->device, fblock,
     773                            BLOCK_FLAGS_NOREAD);
    762774                        if (rc != EOK) {
    763775                                ext4_balloc_free_block(inode_ref, fblock);
    764776                                return rc;
    765777                        }
    766 
     778                       
    767779                        /* Put back not modified old block */
    768780                        block_put(path_ptr->block);
    769 
     781                       
    770782                        /* Initialize newly allocated block and remember it */
    771783                        memset(block->data, 0, block_size);
    772784                        path_ptr->block = block;
    773 
     785                       
    774786                        /* Update pointers in extent path structure */
    775787                        path_ptr->header = block->data;
     
    779791                                ext4_extent_index_set_leaf(path_ptr->index, (path_ptr + 1)->block->lba);
    780792                                limit = (block_size - sizeof(ext4_extent_header_t)) /
    781                                                                         sizeof(ext4_extent_index_t);
     793                                    sizeof(ext4_extent_index_t);
    782794                        } else {
    783795                                path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header);
    784796                                ext4_extent_set_first_block(path_ptr->extent, iblock);
    785797                                limit = (block_size - sizeof(ext4_extent_header_t)) /
    786                                                                         sizeof(ext4_extent_t);
     798                                    sizeof(ext4_extent_t);
    787799                        }
    788 
     800                       
    789801                        /* Initialize on-disk structure (header) */
    790802                        ext4_extent_header_set_entries_count(path_ptr->header, 1);
     
    793805                        ext4_extent_header_set_depth(path_ptr->header, path_ptr->depth);
    794806                        ext4_extent_header_set_generation(path_ptr->header, 0);
    795 
     807                       
    796808                        path_ptr->block->dirty = true;
    797 
     809                       
    798810                        /* Jump to the preceeding item */
    799811                        path_ptr--;
    800 
    801812                } else {
    802 
    803813                        /* Node with free space */
    804814                        if (path_ptr->depth) {
     
    810820                                ext4_extent_set_first_block(path_ptr->extent, iblock);
    811821                        }
    812 
     822                       
    813823                        ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);
    814824                        path_ptr->block->dirty = true;
    815 
     825                       
    816826                        /* No more splitting needed */
    817827                        return EOK;
    818828                }
    819 
    820         }
    821 
     829        }
     830       
    822831        assert(path_ptr == path);
    823 
     832       
    824833        /* Should be the root split too? */
    825 
     834       
    826835        uint16_t entries = ext4_extent_header_get_entries_count(path->header);
    827836        uint16_t limit = ext4_extent_header_get_max_entries_count(path->header);
    828 
     837       
    829838        if (entries == limit) {
    830 
    831839                uint32_t new_fblock;
    832                 rc = ext4_balloc_alloc_block(inode_ref, &new_fblock);
    833                 if (rc != EOK) {
     840                int rc = ext4_balloc_alloc_block(inode_ref, &new_fblock);
     841                if (rc != EOK)
    834842                        return rc;
    835                 }
    836 
     843               
    837844                block_t *block;
    838                 rc = block_get(&block, inode_ref->fs->device,
    839                                 new_fblock, BLOCK_FLAGS_NOREAD);
    840                 if (rc != EOK) {
     845                rc = block_get(&block, inode_ref->fs->device, new_fblock,
     846                    BLOCK_FLAGS_NOREAD);
     847                if (rc != EOK)
    841848                        return rc;
    842                 }
    843 
     849               
    844850                /* Initialize newly allocated block */
    845851                memset(block->data, 0, block_size);
    846 
     852               
    847853                /* Move data from root to the new block */
    848854                memcpy(block->data, inode_ref->inode->blocks,
    849                                 EXT4_INODE_BLOCKS * sizeof(uint32_t));
    850 
    851                 // Data block initialized !!!
    852 
     855                    EXT4_INODE_BLOCKS * sizeof(uint32_t));
     856               
     857                /* Data block is initialized */
     858               
    853859                block_t *root_block = path->block;
    854860                uint16_t root_depth = path->depth;
    855861                ext4_extent_header_t *root_header = path->header;
    856 
     862               
    857863                /* Make space for tree growing */
    858864                ext4_extent_path_t *new_root = path;
    859865                ext4_extent_path_t *old_root = path + 1;
    860 
     866               
    861867                size_t nbytes = sizeof(ext4_extent_path_t) * (path->depth + 1);
    862868                memmove(old_root, new_root, nbytes);
    863869                memset(new_root, 0, sizeof(ext4_extent_path_t));
    864 
     870               
    865871                /* Update old root structure */
    866872                old_root->block = block;
    867873                old_root->header = (ext4_extent_header_t *)block->data;
    868 
     874               
    869875                /* Add new entry and update limit for entries */
    870876                if (old_root->depth) {
    871877                        limit = (block_size - sizeof(ext4_extent_header_t)) /
    872                                                                 sizeof(ext4_extent_index_t);
     878                            sizeof(ext4_extent_index_t);
    873879                        old_root->index = EXT4_EXTENT_FIRST_INDEX(old_root->header) + entries;
    874880                        ext4_extent_index_set_first_block(old_root->index, iblock);
     
    877883                } else {
    878884                        limit = (block_size - sizeof(ext4_extent_header_t)) /
    879                                                                 sizeof(ext4_extent_t);
     885                            sizeof(ext4_extent_t);
    880886                        old_root->extent = EXT4_EXTENT_FIRST(old_root->header) + entries;
    881887                        ext4_extent_set_first_block(old_root->extent, iblock);
    882888                        old_root->index = NULL;
    883889                }
     890               
    884891                ext4_extent_header_set_entries_count(old_root->header, entries + 1);
    885892                ext4_extent_header_set_max_entries_count(old_root->header, limit);
    886 
     893               
    887894                old_root->block->dirty = true;
    888 
     895               
    889896                /* Re-initialize new root metadata */
    890897                new_root->depth = root_depth + 1;
     
    893900                new_root->extent = NULL;
    894901                new_root->index = EXT4_EXTENT_FIRST_INDEX(new_root->header);
    895 
     902               
    896903                ext4_extent_header_set_depth(new_root->header, new_root->depth);
    897 
     904               
    898905                /* Create new entry in root */
    899906                ext4_extent_header_set_entries_count(new_root->header, 1);
    900907                ext4_extent_index_set_first_block(new_root->index, 0);
    901908                ext4_extent_index_set_leaf(new_root->index, new_fblock);
    902 
     909               
    903910                new_root->block->dirty = true;
    904 
    905911        } else {
    906 
    907912                if (path->depth) {
    908913                        path->index = EXT4_EXTENT_FIRST_INDEX(path->header) + entries;
     
    913918                        ext4_extent_set_first_block(path->extent, iblock);
    914919                }
    915 
     920               
    916921                ext4_extent_header_set_entries_count(path->header, entries + 1);
    917922                path->block->dirty = true;
    918923        }
    919 
     924       
    920925        return EOK;
    921926}
     
    927932 * It includes possible extent tree modifications (splitting).
    928933 *<
    929  * @param inode_ref                     i-node to append block to
    930  * @param iblock                        output logical number of newly allocated block
    931  * @param fblock                        output physical block address of newly allocated block
    932  * @return                                      error code
    933  */
    934 int ext4_extent_append_block(ext4_inode_ref_t *inode_ref,
    935                 uint32_t *iblock, uint32_t *fblock, bool update_size)
    936 {
    937         int rc = EOK;
    938 
     934 * @param inode_ref I-node to append block to
     935 * @param iblock    Output logical number of newly allocated block
     936 * @param fblock    Output physical block address of newly allocated block
     937 *
     938 * @return Error code
     939 *
     940 */
     941int ext4_extent_append_block(ext4_inode_ref_t *inode_ref, uint32_t *iblock,
     942    uint32_t *fblock, bool update_size)
     943{
    939944        ext4_superblock_t *sb = inode_ref->fs->superblock;
    940945        uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
    941946        uint32_t block_size = ext4_superblock_get_block_size(sb);
    942 
     947       
    943948        /* Calculate number of new logical block */
    944949        uint32_t new_block_idx = 0;
    945950        if (inode_size > 0) {
    946                 if ((inode_size % block_size) != 0) {
     951                if ((inode_size % block_size) != 0)
    947952                        inode_size += block_size - (inode_size % block_size);
    948                 }
     953               
    949954                new_block_idx = inode_size / block_size;
    950955        }
    951 
     956       
    952957        /* Load the nearest leaf (with extent) */
    953958        ext4_extent_path_t *path;
    954         rc = ext4_extent_find_extent(inode_ref, new_block_idx, &path);
    955         if (rc != EOK) {
     959        int rc = ext4_extent_find_extent(inode_ref, new_block_idx, &path);
     960        if (rc != EOK)
    956961                return rc;
    957         }
    958 
     962       
    959963        /* Jump to last item of the path (extent) */
    960964        ext4_extent_path_t *path_ptr = path;
    961         while (path_ptr->depth != 0) {
     965        while (path_ptr->depth != 0)
    962966                path_ptr++;
    963         }
    964 
     967       
    965968        /* Add new extent to the node if not present */
    966         if (path_ptr->extent == NULL) {
     969        if (path_ptr->extent == NULL)
    967970                goto append_extent;
    968         }
    969 
     971       
    970972        uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);
    971973        uint16_t block_limit = (1 << 15);
    972 
     974       
    973975        uint32_t phys_block = 0;
    974976        if (block_count < block_limit) {
    975 
    976977                /* There is space for new block in the extent */
    977 
    978978                if (block_count == 0) {
    979 
    980979                        /* Existing extent is empty */
    981 
    982980                        rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
    983                         if (rc != EOK) {
     981                        if (rc != EOK)
    984982                                goto finish;
    985                         }
    986 
     983                       
    987984                        /* Initialize extent */
    988985                        ext4_extent_set_first_block(path_ptr->extent, new_block_idx);
    989986                        ext4_extent_set_start(path_ptr->extent, phys_block);
    990987                        ext4_extent_set_block_count(path_ptr->extent, 1);
    991 
     988                       
    992989                        /* Update i-node */
    993990                        if (update_size) {
     
    995992                                inode_ref->dirty = true;
    996993                        }
    997 
     994                       
    998995                        path_ptr->block->dirty = true;
    999 
     996                       
    1000997                        goto finish;
    1001998                } else {
    1002 
    1003999                        /* Existing extent contains some blocks */
    1004 
    10051000                        phys_block = ext4_extent_get_start(path_ptr->extent);
    10061001                        phys_block += ext4_extent_get_block_count(path_ptr->extent);
    1007 
     1002                       
    10081003                        /* Check if the following block is free for allocation */
    10091004                        bool free;
    10101005                        rc = ext4_balloc_try_alloc_block(inode_ref, phys_block, &free);
    1011                         if (rc != EOK) {
     1006                        if (rc != EOK)
    10121007                                goto finish;
    1013                         }
    1014 
    1015                         if (! free) {
    1016                                 /* target is not free, new block must be appended to new extent */
     1008                       
     1009                        if (!free) {
     1010                                /* Target is not free, new block must be appended to new extent */
    10171011                                goto append_extent;
    10181012                        }
    1019 
    1020 
     1013                       
    10211014                        /* Update extent */
    10221015                        ext4_extent_set_block_count(path_ptr->extent, block_count + 1);
    1023 
     1016                       
    10241017                        /* Update i-node */
    10251018                        if (update_size) {
     
    10271020                                inode_ref->dirty = true;
    10281021                        }
    1029 
     1022                       
    10301023                        path_ptr->block->dirty = true;
    1031 
     1024                       
    10321025                        goto finish;
    10331026                }
    10341027        }
    1035 
    1036 /* Append new extent to the tree */
     1028       
     1029       
    10371030append_extent:
    1038 
     1031        /* Append new extent to the tree */
    10391032        phys_block = 0;
    1040 
     1033       
    10411034        /* Allocate new data block */
    10421035        rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
    1043         if (rc != EOK) {
     1036        if (rc != EOK)
    10441037                goto finish;
    1045         }
    1046 
     1038       
    10471039        /* Append extent for new block (includes tree splitting if needed) */
    10481040        rc = ext4_extent_append_extent(inode_ref, path, new_block_idx);
     
    10511043                goto finish;
    10521044        }
    1053 
     1045       
    10541046        uint32_t tree_depth = ext4_extent_header_get_depth(path->header);
    10551047        path_ptr = path + tree_depth;
    1056 
     1048       
    10571049        /* Initialize newly created extent */
    10581050        ext4_extent_set_block_count(path_ptr->extent, 1);
    10591051        ext4_extent_set_first_block(path_ptr->extent, new_block_idx);
    10601052        ext4_extent_set_start(path_ptr->extent, phys_block);
    1061 
     1053       
    10621054        /* Update i-node */
    10631055        if (update_size) {
     
    10651057                inode_ref->dirty = true;
    10661058        }
    1067 
     1059       
    10681060        path_ptr->block->dirty = true;
    1069 
    1070 
     1061       
    10711062finish:
    10721063        /* Set return values */
    10731064        *iblock = new_block_idx;
    10741065        *fblock = phys_block;
    1075 
    1076         /* Put loaded blocks
     1066       
     1067        /*
     1068         * Put loaded blocks
    10771069         * starting from 1: 0 is a block with inode data
    10781070         */
    10791071        for (uint16_t i = 1; i <= path->depth; ++i) {
    1080                 if (path[i].block) {
     1072                if (path[i].block)
    10811073                        block_put(path[i].block);
    1082                 }
    1083         }
    1084 
     1074        }
     1075       
    10851076        /* Destroy temporary data structure */
    10861077        free(path);
    1087 
     1078       
    10881079        return rc;
    10891080}
     
    10911082/**
    10921083 * @}
    1093  */ 
     1084 */
Note: See TracChangeset for help on using the changeset viewer.