Changeset 82cb6768 in mainline for uspace/lib/ext4/libext4_extent.c


Ignore:
Timestamp:
2012-04-10T20:01:46Z (12 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f2a3e57
Parents:
b73530a
Message:

debugged version of splitting root extent node

File:
1 edited

Legend:

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

    rb73530a r82cb6768  
    192192        if (entries_count == 0) {
    193193                // this leaf is empty
    194                 EXT4FS_DBG("EMPTY LEAF");
     194//              EXT4FS_DBG("EMPTY LEAF");
    195195                *extent = NULL;
    196196                return;
     
    379379        uint32_t fblock = ext4_extent_index_get_leaf(index);
    380380
    381         EXT4FS_DBG("fblock = \%u", fblock);
     381//      EXT4FS_DBG("fblock = \%u", fblock);
    382382
    383383        rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NOREAD);
     
    543543        // Put loaded blocks
    544544        // From 1 -> 0 is a block with inode data
    545         for (uint16_t i = 1; i < path->depth; ++i) {
     545        for (uint16_t i = 1; i <= path->depth; ++i) {
    546546                if (path[i].block) {
    547547                        block_put(path[i].block);
     
    553553
    554554        return rc;
     555}
     556
     557static int ext4_extent_append_extent(ext4_inode_ref_t *inode_ref,
     558                ext4_extent_path_t *path, ext4_extent_path_t **last_path_item,
     559                uint32_t iblock)
     560{
     561        int rc;
     562
     563        ext4_extent_path_t *path_ptr = *last_path_item;
     564
     565        uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header);
     566        uint16_t limit = ext4_extent_header_get_max_entries_count(path_ptr->header);
     567
     568        // Trivial way - no splitting
     569        if (entries < limit) {
     570                ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);
     571                path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries;
     572                ext4_extent_set_block_count(path_ptr->extent, 0);
     573                ext4_extent_set_first_block(path_ptr->extent, iblock);
     574                ext4_extent_set_start(path_ptr->extent, 0);
     575                path_ptr->block->dirty = true;
     576
     577                return EOK;
     578        }
     579
     580        uint32_t block_size =
     581                        ext4_superblock_get_block_size(inode_ref->fs->superblock);
     582
     583        // Trivial tree - grow
     584        if (path_ptr == path) {
     585
     586//              EXT4FS_DBG("splitting extent root");
     587
     588                uint32_t new_fblock;
     589                rc = ext4_balloc_alloc_block(inode_ref, &new_fblock);
     590                if (rc != EOK) {
     591                        EXT4FS_DBG("error in block allocation");
     592                        return rc;
     593                }
     594
     595//              EXT4FS_DBG("allocated new node \%u", new_fblock);
     596
     597                block_t *block;
     598                rc = block_get(&block, inode_ref->fs->device,
     599                                new_fblock, BLOCK_FLAGS_NOREAD);
     600                if (rc != EOK) {
     601                        EXT4FS_DBG("error in block_get");
     602                        return rc;
     603                }
     604
     605                memset(block->data, 0, block_size);
     606
     607                // Move data from root to the new block
     608                memcpy(block->data, inode_ref->inode->blocks,
     609                                EXT4_INODE_BLOCKS * sizeof(uint32_t));
     610
     611                path_ptr++;
     612                path_ptr->block = block;
     613                path_ptr->header = (ext4_extent_header_t *)block->data;
     614                path_ptr->depth = ext4_extent_header_get_depth(path_ptr->header);
     615                path_ptr->index = NULL;
     616
     617                uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header);
     618                path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries;
     619                ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);
     620                uint16_t limit = (block_size - sizeof(ext4_extent_header_t)) /
     621                                sizeof(ext4_extent_t);
     622                ext4_extent_header_set_max_entries_count(path_ptr->header, limit);
     623
     624                // Modify root (in inode)
     625                path->depth = 1;
     626                path->extent = NULL;
     627                path->index = EXT4_EXTENT_FIRST_INDEX(path->header);
     628
     629                ext4_extent_header_set_depth(path->header, path_ptr->depth + 1);
     630                ext4_extent_header_set_entries_count(path->header, 1);
     631
     632                ext4_extent_index_set_first_block(path->index, 0);
     633                ext4_extent_index_set_leaf(path->index, new_fblock);
     634
     635                path_ptr->block->dirty = true;
     636                path->block->dirty = true;
     637
     638                *last_path_item = path_ptr;
     639
     640                return EOK;
     641        }
     642
     643        assert(false);
     644
     645        // start splitting
     646        uint32_t fblock = 0;
     647
     648        path_ptr--;
     649
     650        while (path_ptr > path) {
     651
     652                rc = ext4_balloc_alloc_block(inode_ref, &fblock);
     653                if (rc != EOK) {
     654                        return rc;
     655                }
     656
     657                block_t *block;
     658                rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NOREAD);
     659                if (rc != EOK) {
     660                        ext4_balloc_free_block(inode_ref, fblock);
     661                        return rc;
     662                }
     663
     664                // Init block
     665                memset(block->data, 0, block_size);
     666
     667                // Not modified
     668                block_put(path_ptr->block);
     669                path_ptr->block = block;
     670
     671                path_ptr->header = block->data;
     672
     673                if (path_ptr->depth) {
     674                        path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header);
     675                } else {
     676                        path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header);
     677                }
     678        }
     679
     680        return EOK;
    555681}
    556682
     
    564690        uint32_t block_size = ext4_superblock_get_block_size(sb);
    565691
     692        // Calculate number of new logical block
    566693        uint32_t new_block_idx = 0;
    567694        if (inode_size > 0) {
     
    572699        }
    573700
     701        // Load the nearest leaf (with extent)
    574702        ext4_extent_path_t *path;
    575703        rc = ext4_extent_find_extent(inode_ref, new_block_idx, &path);
     
    584712        }
    585713
    586         // if extent == NULL -> add extent to empty leaf
     714        uint32_t phys_block = 0;
     715
     716        // Add new extent to the node
    587717        if (path_ptr->extent == NULL) {
    588 
    589                 EXT4FS_DBG("NULL extent");
    590 
    591                 ext4_extent_t *ext = EXT4_EXTENT_FIRST(path_ptr->header);
    592                 ext4_extent_set_block_count(ext, 0);
    593 
    594                 ext4_extent_header_set_entries_count(path_ptr->header, 1);
    595 
    596                 path_ptr->extent = ext;
    597         }
    598 
    599         uint32_t phys_block;
    600 
    601         if (ext4_extent_get_block_count(path_ptr->extent) == 0) {
    602 
    603                 EXT4FS_DBG("no blocks in extent");
    604 
    605                 // Add first block to the extent
    606 
    607                 rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
    608                 if (rc != EOK) {
    609                         EXT4FS_DBG("error in allocation");
     718                goto append_extent;
     719        }
     720
     721        uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);
     722        uint16_t block_limit = (1 << 15);
     723
     724        if (block_count < block_limit) {
     725
     726                if (block_count == 0) {
     727
     728                        rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
     729                        if (rc != EOK) {
     730                        // TODO error, cleanup
     731                                assert(false);
     732                        }
     733
     734                        ext4_extent_set_first_block(path_ptr->extent, new_block_idx);
     735                        ext4_extent_set_start(path_ptr->extent, phys_block);
     736                        ext4_extent_set_block_count(path_ptr->extent, 1);
     737
     738                        path_ptr->block->dirty = true;
     739
    610740                        goto finish;
    611                 }
    612 
    613                 ext4_extent_set_block_count(path_ptr->extent, 1);
    614                 ext4_extent_set_start(path_ptr->extent, phys_block);
    615                 ext4_extent_set_first_block(path_ptr->extent, new_block_idx);
    616 
    617                 path_ptr->block->dirty = true;
    618 
     741                } else {
     742
     743                        phys_block = ext4_extent_get_start(path_ptr->extent);
     744                        phys_block += ext4_extent_get_block_count(path_ptr->extent);
     745
     746                        bool free;
     747                        rc = ext4_balloc_try_alloc_block(inode_ref, phys_block, &free);
     748                        if (rc != EOK) {
     749                                // TODO error
     750                                assert(false);
     751                        }
     752
     753                        if (! free) {
     754                                // target is not free
     755//                              EXT4FS_DBG("target not free, \%u", phys_block);
     756                                goto append_extent;
     757                        }
     758
     759
     760                        ext4_extent_set_block_count(path_ptr->extent, block_count + 1);
     761
     762                        path_ptr->block->dirty = true;
     763
     764                        goto finish;
     765                }
     766        }
     767
     768        assert(false);
     769
     770append_extent:
     771
     772        phys_block = 0;
     773        // Allocate and insert insert new block
     774        rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
     775        if (rc != EOK) {
     776                EXT4FS_DBG("error in block allocation, rc = \%d", rc);
    619777                goto finish;
    620 
    621         } else {
    622                 // try allocate succeeding extent block
    623 
    624                 EXT4FS_DBG("existing extent");
    625 
    626                 uint16_t blocks = ext4_extent_get_block_count(path_ptr->extent);
    627 
    628                 if (blocks < (1 << 15)) {
    629                         // there is place for more blocks
    630 
    631                         EXT4FS_DBG("appending block to existing extent");
    632 
    633                         uint64_t last = ext4_extent_get_start(path_ptr->extent) + blocks - 1;
    634 
    635                         rc = ext4_balloc_try_alloc_block(inode_ref, last + 1);
    636                         if (rc == EOK) {
    637                                 path_ptr->block->dirty = true;
    638                                 ext4_extent_set_block_count(path_ptr->extent, blocks + 1);
    639                                 phys_block = last + 1;
    640                                 goto finish;
    641                         }
    642 
    643                         if (rc != EINVAL) {
    644                                 goto finish;
    645                         }
    646                 }
    647 
    648                 // Add new extent
    649                 // TODO
    650                 assert(false);
    651         }
    652 
     778        }
     779
     780//      EXT4FS_DBG("allocated \%u", phys_block);
     781
     782        rc = ext4_extent_append_extent(inode_ref, path, &path_ptr, new_block_idx);
     783        if (rc != EOK) {
     784                ext4_balloc_free_block(inode_ref, phys_block);
     785                goto finish;
     786        }
     787
     788        ext4_extent_set_block_count(path_ptr->extent, 1);
     789        ext4_extent_set_first_block(path_ptr->extent, new_block_idx);
     790        ext4_extent_set_start(path_ptr->extent, phys_block);
     791
     792        path_ptr->block->dirty = true;
    653793
    654794finish:
     
    657797        *fblock = phys_block;
    658798
     799//      EXT4FS_DBG("iblock = \%u, fblock = \%u", new_block_idx, phys_block);
     800
    659801        // Put loaded blocks
    660802        // From 1 -> 0 is a block with inode data
    661         for (uint16_t i = 1; i < path->depth; ++i) {
     803        for (uint16_t i = 1; i <= path->depth; ++i) {
    662804                if (path[i].block) {
    663805                        block_put(path[i].block);
Note: See TracChangeset for help on using the changeset viewer.