Changeset 12b4a7f in mainline


Ignore:
Timestamp:
2011-11-07T16:23:30Z (13 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
43a9968
Parents:
052e82d
Message:

functional truncate operation (only to lower size actually), except extent files

Location:
uspace
Files:
6 edited

Legend:

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

    r052e82d r12b4a7f  
    3333/**
    3434 * @file        libext4_bitmap.c
    35  * @brief       TODO
     35 * @brief       Ext4 bitmap (block & inode) operations.
    3636 */
    3737
     
    9191        free_blocks++;
    9292        ext4_block_group_set_free_blocks_count(bg_ref->block_group, free_blocks);
     93        bg_ref->dirty = true;
    9394
    9495        rc = ext4_filesystem_put_block_group_ref(bg_ref);
  • uspace/lib/ext4/libext4_block_group.h

    r052e82d r12b4a7f  
    6565        block_t *block; // Reference to a block containing this block group descr
    6666        ext4_block_group_t *block_group;
     67        bool dirty;
    6768} ext4_block_group_ref_t;
    6869
  • uspace/lib/ext4/libext4_filesystem.c

    r052e82d r12b4a7f  
    152152        }
    153153
    154         //EXT4FS_DBG("desc size = \%u", (uint32_t)ext4_superblock_get_desc_size(fs->superblock));
    155 
    156154        descriptors_per_block = ext4_superblock_get_block_size(fs->superblock)
    157155            / ext4_superblock_get_desc_size(fs->superblock);
     
    171169
    172170        newref->block_group = newref->block->data + offset;
     171        newref->dirty = false;
    173172
    174173        *ref = newref;
     
    180179{
    181180        int rc;
     181
     182        if (ref->dirty) {
     183                ref->block->dirty = true;
     184        }
    182185
    183186        rc = block_put(ref->block);
     
    375378        /* TODO handle extents */
    376379
     380
    377381        /* Handle simple case when we are dealing with direct reference */
    378382        if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
    379                 EXT4FS_DBG("direct block");
    380                 fblock = ext4_inode_get_direct_block(inode, (uint32_t)iblock);
     383                fblock = ext4_inode_get_direct_block(inode, iblock);
    381384                // Sparse file
    382385                if (fblock == 0) {
     
    386389                ext4_inode_set_direct_block(inode, iblock, 0);
    387390                return ext4_bitmap_free_block(fs, fblock);
    388         } else {
    389 
    390                 /* Determine the indirection level needed to get the desired block */
    391                 level = -1;
    392                 for (i = 1; i < 4; i++) {
    393                         if (iblock < fs->inode_block_limits[i]) {
    394                                 level = i;
    395                                 break;
    396                         }
    397                 }
    398 
    399                 if (level == -1) {
    400                         return EIO;
    401                 }
    402 
    403                 /* Compute offsets for the topmost level */
    404                 block_offset_in_level = iblock - fs->inode_block_limits[level-1];
    405                 current_block = ext4_inode_get_indirect_block(inode, level-1);
     391        }
     392
     393
     394        /* Determine the indirection level needed to get the desired block */
     395        level = -1;
     396        for (i = 1; i < 4; i++) {
     397                if (iblock < fs->inode_block_limits[i]) {
     398                        level = i;
     399                        break;
     400                }
     401        }
     402
     403        if (level == -1) {
     404                return EIO;
     405        }
     406
     407        /* Compute offsets for the topmost level */
     408        block_offset_in_level = iblock - fs->inode_block_limits[level-1];
     409        current_block = ext4_inode_get_indirect_block(inode, level-1);
     410        offset_in_block = block_offset_in_level / fs->inode_blocks_per_level[level-1];
     411
     412        /* Navigate through other levels, until we find the block number
     413         * or find null reference meaning we are dealing with sparse file
     414         */
     415        while (level > 0) {
     416                rc = block_get(&block, fs->device, current_block, 0);
     417                if (rc != EOK) {
     418                        return rc;
     419                }
     420
     421                current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]);
     422
     423                // Set zero
     424                if (level == 1) {
     425                        ((uint32_t*)block->data)[offset_in_block] = host2uint32_t_le(0);
     426                        block->dirty = true;
     427                }
     428
     429                rc = block_put(block);
     430                if (rc != EOK) {
     431                        return rc;
     432                }
     433
     434                level -= 1;
     435
     436                /* If we are on the last level, break here as
     437                 * there is no next level to visit
     438                 */
     439                if (level == 0) {
     440                        break;
     441                }
     442
     443                /* Visit the next level */
     444                block_offset_in_level %= fs->inode_blocks_per_level[level];
    406445                offset_in_block = block_offset_in_level / fs->inode_blocks_per_level[level-1];
    407 
    408                 /* Navigate through other levels, until we find the block number
    409                  * or find null reference meaning we are dealing with sparse file
    410                  */
    411                 while (level > 0) {
    412                         rc = block_get(&block, fs->device, current_block, 0);
    413                         if (rc != EOK) {
    414                                 return rc;
    415                         }
    416 
    417                         current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]);
    418 
    419                         // Set zero
    420                         if (level == 1) {
    421                                 ((uint32_t*)block->data)[offset_in_block] = host2uint32_t_le(0);
    422                                 block->dirty = true;
    423                         }
    424 
    425                         rc = block_put(block);
    426                         if (rc != EOK) {
    427                                 return rc;
    428                         }
    429 
    430                         level -= 1;
    431 
    432                         /* If we are on the last level, break here as
    433                          * there is no next level to visit
    434                          */
    435                         if (level == 0) {
    436                                 break;
    437                         }
    438 
    439                         /* Visit the next level */
    440                         block_offset_in_level %= fs->inode_blocks_per_level[level];
    441                         offset_in_block = block_offset_in_level / fs->inode_blocks_per_level[level-1];
    442                 }
    443 
    444                 fblock = current_block;
    445 
    446                 if (fblock == 0) {
    447                         return EOK;
    448                 }
     446        }
     447
     448        fblock = current_block;
     449
     450        if (fblock == 0) {
     451                return EOK;
    449452        }
    450453
  • uspace/lib/ext4/libext4_inode.c

    r052e82d r12b4a7f  
    193193}
    194194
     195bool ext4_inode_can_truncate(ext4_inode_t *inode)
     196{
     197         if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)
     198                         || ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)) {
     199                 return false;
     200         }
     201
     202
     203         if (ext4_inode_get_mode(inode) == EXT4_INODE_MODE_FILE
     204                         || ext4_inode_get_mode(inode) == EXT4_INODE_MODE_DIRECTORY) {
     205                 return true;
     206         }
     207
     208         return false;
     209}
     210
    195211/**
    196212 * @}
  • uspace/lib/ext4/libext4_inode.h

    r052e82d r12b4a7f  
    187187extern ext4_extent_header_t * ext4_inode_get_extent_header(ext4_inode_t *);
    188188extern bool ext4_inode_has_flag(ext4_inode_t *, uint32_t);
     189extern bool ext4_inode_can_truncate(ext4_inode_t *);
    189190
    190191#endif
  • uspace/srv/fs/ext4fs/ext4fs_ops.c

    r052e82d r12b4a7f  
    954954        fs = enode->instance->filesystem;
    955955
     956
     957        if (! ext4_inode_can_truncate(inode_ref->inode)) {
     958                // Unable to truncate
     959                return EINVAL;
     960        }
     961
    956962        old_size = ext4_inode_get_size(fs->superblock, inode_ref->inode);
    957 
    958         printf("old size = \%llu, new size = \%llu\n", old_size, new_size);
    959963
    960964        if (old_size == new_size) {
     
    962966        } else {
    963967
    964                 //int rc;
    965968                uint32_t block_size;
    966969                uint32_t blocks_count, total_blocks;
     
    970973
    971974                if (old_size < new_size) {
    972                         // TODO don't return immediately
    973                         EXT4FS_DBG("expand the file");
     975                        // Currently not supported to expand the file
     976                        // TODO
     977                        EXT4FS_DBG("trying to expand the file");
    974978                        return EINVAL;
    975979                }
    976 
    977                 EXT4FS_DBG("cut the end of the file !");
    978980
    979981                size_diff = old_size - new_size;
     
    990992                inode_ref->dirty = true;
    991993
    992                 for (i = 0; i< blocks_count; ++i) {
     994                // starting from 1 because of logical blocks are numbered from 0
     995                for (i = 1; i <= blocks_count; ++i) {
    993996                        // TODO check retval
     997                        // TODO decrement inode->blocks_count
     998
    994999                        ext4_filesystem_release_inode_block(fs, inode_ref, total_blocks - i);
    9951000                }
Note: See TracChangeset for help on using the changeset viewer.