Changeset 1e65444 in mainline


Ignore:
Timestamp:
2011-11-09T17:52:33Z (12 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2b9e142
Parents:
35f48f2
Message:

more functional file writing - indirect blocks too

Location:
uspace
Files:
6 edited

Legend:

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

    r35f48f2 r1e65444  
    4343static void ext4_bitmap_free_bit(uint8_t *bitmap, uint32_t index)
    4444{
     45        // Block numbers are 1-based
    4546        uint32_t byte_index = index / 8;
    4647        uint32_t bit_index = index % 8;
     48
     49//      EXT4FS_DBG("freeing block \%u, byte \%u and bit \%u", index, byte_index, bit_index);
    4750
    4851        uint8_t *target = bitmap + byte_index;
     
    5962        int i;
    6063        uint32_t idx = 0;
     64        uint8_t value, new_value;
    6165
    6266        while (pos < bitmap + size) {
     
    7276        if (pos < bitmap + size) {
    7377
     78//              EXT4FS_DBG("byte found \%u", (uint32_t)(pos - bitmap));
     79
    7480                for(i = 0; i < 8; ++i) {
    75                         if ((*pos & (1 << i)) == 0) {
     81                        value = *pos;
     82
     83                        if ((value & (1 << i)) == 0) {
    7684                                // free bit found
    77                                 *pos |= (1 << i);
    78                                 *index = idx;
     85//                              EXT4FS_DBG("bit found \%u", i);
     86                                new_value = value | (1 << i);
     87                                *pos = new_value;
     88                                *index = idx + i;
    7989                                return EOK;
    8090                        }
    81 
    82                         idx++;
    8391                }
    8492        }
     
    98106
    99107        blocks_per_group = ext4_superblock_get_blocks_per_group(fs->superblock);
    100         block_group = block_index / blocks_per_group;
    101         index_in_group = block_index % blocks_per_group;
     108        block_group = ((block_index - 1) / blocks_per_group);
     109        index_in_group = (block_index - 1) % blocks_per_group;
    102110
    103111        rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
     
    133141                return rc;
    134142        }
     143
     144        EXT4FS_DBG("block \%u released", block_index);
    135145
    136146        return EOK;
     
    148158
    149159        inodes_per_group = ext4_superblock_get_inodes_per_group(fs->superblock);
    150         block_group = inode_ref->index / inodes_per_group;
     160        block_group = (inode_ref->index - 1) / inodes_per_group;
    151161
    152162        block_size = ext4_superblock_get_block_size(fs->superblock);
     
    166176
    167177        rc = ext4_bitmap_find_free_bit_and_set(block->data, &rel_block_idx, block_size);
    168 
    169 
    170178        if (rc != EOK) {
    171179                EXT4FS_DBG("no block found");
    172180                // TODO if ENOSPC - try next block group - try next block groups
    173181        }
     182
     183        block->dirty = true;
     184
     185        // TODO check retval
     186        block_put(block);
    174187
    175188        // TODO decrement superblock free blocks count
     
    179192
    180193        uint32_t bg_free_blocks = ext4_block_group_get_free_blocks_count(bg_ref->block_group);
    181         bg_free_blocks++;
     194        bg_free_blocks--;
    182195        ext4_block_group_set_free_blocks_count(bg_ref->block_group, bg_free_blocks);
    183196        bg_ref->dirty = true;
    184197
    185         // return
     198        ext4_filesystem_put_block_group_ref(bg_ref);
     199
    186200        blocks_per_group = ext4_superblock_get_blocks_per_group(fs->superblock);
    187         *fblock = blocks_per_group * block_group + rel_block_idx;
     201
     202        EXT4FS_DBG("block \%u allocated", blocks_per_group * block_group + rel_block_idx + 1);
     203
     204        *fblock = blocks_per_group * block_group + rel_block_idx + 1;
    188205        return EOK;
    189206
  • uspace/lib/ext4/libext4_filesystem.c

    r35f48f2 r1e65444  
    364364
    365365int ext4_filesystem_set_inode_data_block_index(ext4_filesystem_t *fs,
    366                 ext4_inode_t *inode, aoff64_t iblock, uint32_t fblock)
    367 {
    368 
    369 //      int rc;
    370 //      uint32_t offset_in_block;
    371 //      uint32_t current_block;
    372 //      aoff64_t block_offset_in_level;
    373 //      int i;
    374 //      int level;
    375 //      block_t *block;
     366                ext4_inode_ref_t *inode_ref, aoff64_t iblock, uint32_t fblock)
     367{
     368
     369        int rc;
     370        uint32_t offset_in_block;
     371        uint32_t current_block, new_block_addr;
     372        uint32_t block_size;
     373        aoff64_t block_offset_in_level;
     374        int i;
     375        int level;
     376        block_t *block, *new_block;
    376377
    377378        /* Handle inode using extents */
    378379        if (ext4_superblock_has_feature_compatible(fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS) &&
    379                         ext4_inode_has_flag(inode, EXT4_INODE_FLAG_EXTENTS)) {
     380                        ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)) {
    380381                // TODO
    381382                return ENOTSUP;
     
    385386        /* Handle simple case when we are dealing with direct reference */
    386387        if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
    387                 ext4_inode_set_direct_block(inode, (uint32_t)iblock, fblock);
     388                ext4_inode_set_direct_block(inode_ref->inode, (uint32_t)iblock, fblock);
     389                inode_ref->dirty = true;
    388390                return EOK;
    389391        }
    390392
    391 //      /* Determine the indirection level needed to get the desired block */
    392 //      level = -1;
    393 //      for (i = 1; i < 4; i++) {
    394 //              if (iblock < fs->inode_block_limits[i]) {
    395 //                      level = i;
    396 //                      break;
    397 //              }
    398 //      }
    399 //
    400 //      if (level == -1) {
    401 //              return EIO;
    402 //      }
    403 //
    404 //      /* Compute offsets for the topmost level */
    405 //      block_offset_in_level = iblock - fs->inode_block_limits[level-1];
    406 //      current_block = ext4_inode_get_indirect_block(inode, level-1);
    407 //      offset_in_block = block_offset_in_level / fs->inode_blocks_per_level[level-1];
    408 //
    409 //      /* Navigate through other levels, until we find the block number
    410 //       * or find null reference meaning we are dealing with sparse file
    411 //       */
    412 //      while (level > 0) {
    413 //              rc = block_get(&block, fs->device, current_block, 0);
    414 //              if (rc != EOK) {
    415 //                      return rc;
    416 //              }
    417 //
    418 //              current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]);
    419 //
    420 //              rc = block_put(block);
    421 //              if (rc != EOK) {
    422 //                      return rc;
    423 //              }
    424 //
    425 //              if (current_block == 0) {
    426 //                      /* This is a sparse file */
    427 //                      *fblock = 0;
    428 //                      return EOK;
    429 //              }
    430 //
    431 //              level -= 1;
    432 //
    433 //              /* If we are on the last level, break here as
    434 //               * there is no next level to visit
    435 //               */
    436 //              if (level == 0) {
    437 //                      break;
    438 //              }
    439 //
    440 //              /* Visit the next level */
    441 //              block_offset_in_level %= fs->inode_blocks_per_level[level];
    442 //              offset_in_block = block_offset_in_level / fs->inode_blocks_per_level[level-1];
    443 //      }
    444 //
    445 //      *fblock = current_block;
    446 //
    447 //      return EOK;
    448 //
    449 //
     393        /* Determine the indirection level needed to get the desired block */
     394        level = -1;
     395        for (i = 1; i < 4; i++) {
     396                if (iblock < fs->inode_block_limits[i]) {
     397                        level = i;
     398                        break;
     399                }
     400        }
     401
     402        if (level == -1) {
     403                return EIO;
     404        }
     405
     406        block_size = ext4_superblock_get_block_size(fs->superblock);
     407
     408        /* Compute offsets for the topmost level */
     409        block_offset_in_level = iblock - fs->inode_block_limits[level-1];
     410        current_block = ext4_inode_get_indirect_block(inode_ref->inode, level-1);
     411        offset_in_block = block_offset_in_level / fs->inode_blocks_per_level[level-1];
     412
     413        if (current_block == 0) {
     414                rc = ext4_bitmap_alloc_block(fs, inode_ref, &new_block_addr);
     415                if (rc != EOK) {
     416                        // TODO error
     417                }
     418                EXT4FS_DBG("AAA: new addr \%u, level = \%u", new_block_addr, level);
     419
     420                ext4_inode_set_indirect_block(inode_ref->inode, level - 1, new_block_addr);
     421
     422                inode_ref->dirty = true;
     423
     424                rc = block_get(&new_block, fs->device, new_block_addr, BLOCK_FLAGS_NOREAD);
     425                if (rc != EOK) {
     426                        EXT4FS_DBG("block load error");
     427                        // TODO error
     428                }
     429
     430                memset(new_block->data, 0, block_size);
     431                new_block->dirty = true;
     432
     433                rc = block_put(new_block);
     434                if (rc != EOK) {
     435                        EXT4FS_DBG("block put error");
     436                }
     437
     438                current_block = new_block_addr;
     439        }
     440
     441        /* Navigate through other levels, until we find the block number
     442         * or find null reference meaning we are dealing with sparse file
     443         */
     444        while (level > 0) {
     445
     446                rc = block_get(&block, fs->device, current_block, 0);
     447                if (rc != EOK) {
     448                        return rc;
     449                }
     450
     451                current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]);
     452
     453                if (current_block == 0) {
     454                        if (level > 1) {
     455
     456                                rc = ext4_bitmap_alloc_block(fs, inode_ref, &new_block_addr);
     457                                if (rc != EOK) {
     458                                        // TODO error
     459                                }
     460
     461                                rc = block_get(&new_block, fs->device, new_block_addr, BLOCK_FLAGS_NOREAD);
     462                                if (rc != EOK) {
     463                                        // TODO error
     464                                }
     465                                memset(new_block->data, 0, block_size);
     466                                new_block->dirty = true;
     467
     468                                block_put(new_block);
     469
     470                                ((uint32_t*)block->data)[offset_in_block] = host2uint32_t_le(new_block_addr);
     471                                block->dirty = true;
     472                                current_block = new_block_addr;
     473                        } else {
     474                                ((uint32_t*)block->data)[offset_in_block] = host2uint32_t_le(fblock);
     475                                block->dirty = true;
     476                        }
     477                }
     478
     479                rc = block_put(block);
     480                if (rc != EOK) {
     481                        return rc;
     482                }
     483
     484                level -= 1;
     485
     486                /* If we are on the last level, break here as
     487                 * there is no next level to visit
     488                 */
     489                if (level == 0) {
     490                        break;
     491                }
     492
     493                /* Visit the next level */
     494                block_offset_in_level %= fs->inode_blocks_per_level[level];
     495                offset_in_block = block_offset_in_level / fs->inode_blocks_per_level[level-1];
     496        }
    450497
    451498        return EOK;
  • uspace/lib/ext4/libext4_filesystem.h

    r35f48f2 r1e65444  
    6363        ext4_inode_t *, aoff64_t iblock, uint32_t *);
    6464extern int ext4_filesystem_set_inode_data_block_index(ext4_filesystem_t *,
    65                 ext4_inode_t *, aoff64_t, uint32_t);
     65                ext4_inode_ref_t *, aoff64_t, uint32_t);
    6666extern int ext4_filesystem_release_inode_block(ext4_filesystem_t *,
    6767                ext4_inode_ref_t *, uint32_t);
  • uspace/lib/ext4/libext4_inode.c

    r35f48f2 r1e65444  
    9797}
    9898
    99 uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint8_t idx)
     99uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint32_t idx)
    100100{
    101101        assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
     
    103103}
    104104
    105 void ext4_inode_set_direct_block(ext4_inode_t *inode, uint8_t idx, uint32_t fblock)
     105void ext4_inode_set_direct_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
    106106{
    107107        assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
     
    109109}
    110110
    111 uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint8_t idx)
    112 {
    113         assert(idx < EXT4_INODE_INDIRECT_BLOCK_COUNT);
     111uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint32_t idx)
     112{
    114113        return uint32_t_le2host(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);
    115114}
     115
     116void ext4_inode_set_indirect_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
     117{
     118        inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] = host2uint32_t_le(fblock);
     119}
     120
    116121
    117122uint32_t ext4_inode_get_extent_block(ext4_inode_t *inode, uint64_t idx, service_id_t service_id)
  • uspace/lib/ext4/libext4_inode.h

    r35f48f2 r1e65444  
    168168extern uint32_t ext4_inode_get_flags(ext4_inode_t *);
    169169
    170 extern uint32_t ext4_inode_get_direct_block(ext4_inode_t *, uint8_t);
    171 extern void ext4_inode_set_direct_block(ext4_inode_t *, uint8_t, uint32_t);
    172 extern uint32_t ext4_inode_get_indirect_block(ext4_inode_t *, uint8_t);
     170extern uint32_t ext4_inode_get_direct_block(ext4_inode_t *, uint32_t);
     171extern void ext4_inode_set_direct_block(ext4_inode_t *, uint32_t, uint32_t);
     172extern uint32_t ext4_inode_get_indirect_block(ext4_inode_t *, uint32_t);
     173extern void ext4_inode_set_indirect_block(ext4_inode_t *, uint32_t, uint32_t);
    173174extern uint32_t ext4_inode_get_extent_block(ext4_inode_t *, uint64_t, service_id_t);
    174175/*
  • uspace/srv/fs/ext4fs/ext4fs_ops.c

    r35f48f2 r1e65444  
    926926    size_t *wbytes, aoff64_t *nsize)
    927927{
    928         EXT4FS_DBG("");
    929 
    930928        int rc;
    931929        int flags = BLOCK_FLAGS_NONE;
     
    966964        }
    967965
    968         EXT4FS_DBG("bytes == \%u", bytes);
     966//      EXT4FS_DBG("bytes == \%u", bytes);
    969967
    970968        iblock =  pos / block_size;
     
    973971
    974972        if (fblock == 0) {
    975                 EXT4FS_DBG("Allocate block !!!");
     973//              EXT4FS_DBG("Allocate block !!!");
    976974                rc =  ext4_bitmap_alloc_block(fs, inode_ref, &fblock);
    977975                if (rc != EOK) {
     
    981979                }
    982980
    983                 ext4_filesystem_set_inode_data_block_index(fs, inode_ref->inode, iblock, fblock);
     981                ext4_filesystem_set_inode_data_block_index(fs, inode_ref, iblock, fblock);
    984982                inode_ref->dirty = true;
    985983
    986984                flags = BLOCK_FLAGS_NOREAD;
    987985
    988                 EXT4FS_DBG("block \%u allocated", fblock);
     986//              EXT4FS_DBG("block \%u allocated", fblock);
    989987        }
    990988
     
    996994        }
    997995
    998         EXT4FS_DBG("block loaded");
    999 
    1000996        if (flags == BLOCK_FLAGS_NOREAD) {
    1001                 EXT4FS_DBG("fill block with zeros");
     997//              EXT4FS_DBG("fill block with zeros");
    1002998                memset(write_block->data, 0, block_size);
    1003999        }
     
    10051001        rc = async_data_write_finalize(callid, write_block->data + (pos % block_size), bytes);
    10061002        if (rc != EOK) {
     1003                // TODO error
    10071004                EXT4FS_DBG("error in write finalize \%d", rc);
    10081005        }
    10091006
    1010         char *data = write_block->data + (pos % block_size);
    1011         for (uint32_t x = 0; x < bytes; ++x) {
    1012                 printf("%c", data[x]);
    1013         }
    1014         printf("\n");
    1015 
    10161007        write_block->dirty = true;
    10171008
     
    10221013        }
    10231014
    1024         EXT4FS_DBG("writing finished");
     1015//      EXT4FS_DBG("writing finished");
    10251016
    10261017        old_inode_size = ext4_inode_get_size(fs->superblock, inode_ref->inode);
Note: See TracChangeset for help on using the changeset viewer.