Changeset 1e65444 in mainline for uspace/lib/ext4/libext4_filesystem.c


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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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;
Note: See TracChangeset for help on using the changeset viewer.