Browse Source

FIX: an extra block is freed when truncating an inode.

pull/6/head
ngkaho1234 9 years ago
parent
commit
d526904e82
  1. 29
      lwext4/ext4_fs.c

29
lwext4/ext4_fs.c

@ -908,25 +908,26 @@ int ext4_fs_truncate_inode(struct ext4_inode_ref *inode_ref, uint64_t new_size)
} }
/* Compute how many blocks will be released */ /* Compute how many blocks will be released */
uint64_t size_diff = old_size - new_size;
uint32_t block_size = ext4_sb_get_block_size(sb); uint32_t block_size = ext4_sb_get_block_size(sb);
uint32_t diff_blocks_count = size_diff / block_size; uint32_t new_blocks_count = (new_size + block_size - 1) /
if (size_diff % block_size != 0) block_size;
diff_blocks_count++; uint32_t old_blocks_count = (old_size + block_size - 1) /
block_size;
uint32_t old_blocks_count = old_size / block_size; uint32_t diff_blocks_count = old_blocks_count - new_blocks_count;
if (old_size % block_size != 0)
old_blocks_count++;
#if CONFIG_EXTENT_ENABLE #if CONFIG_EXTENT_ENABLE
if ((ext4_sb_has_feature_incompatible(sb, if ((ext4_sb_has_feature_incompatible(sb,
EXT4_FEATURE_INCOMPAT_EXTENTS)) && EXT4_FEATURE_INCOMPAT_EXTENTS)) &&
(ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) { (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) {
/* Extents require special operation */ /* Extents require special operation */
int rc = ext4_extent_release_blocks_from( if (diff_blocks_count) {
inode_ref, old_blocks_count - diff_blocks_count); int rc = ext4_extent_release_blocks_from(
if (rc != EOK) inode_ref,
return rc; new_blocks_count);
if (rc != EOK)
return rc;
}
} else } else
#endif #endif
{ {
@ -934,9 +935,9 @@ int ext4_fs_truncate_inode(struct ext4_inode_ref *inode_ref, uint64_t new_size)
/* Starting from 1 because of logical blocks are numbered from 0 /* Starting from 1 because of logical blocks are numbered from 0
*/ */
for (i = 1; i <= diff_blocks_count; ++i) { for (i = 0; i < diff_blocks_count; ++i) {
int rc = ext4_fs_release_inode_block( int rc = ext4_fs_release_inode_block(
inode_ref, old_blocks_count - i); inode_ref, new_blocks_count + i);
if (rc != EOK) if (rc != EOK)
return rc; return rc;
} }

Loading…
Cancel
Save