ref: 39cfadf99cd75b56c4ee677098960623b5eccce3
parent: 2548f2436138aa5fb080920be0a5ac7e02001199
author: ngkaho1234 <[email protected]>
date: Sun Oct 18 02:17:17 EDT 2015
Multiple fixes related to basic block type 1. uint32_t block address converted to ext4_fsblk_t block address 2. ext4_balloc_find_goal renamed to ext4_fs_indirect_find_goal 3. ext4_balloc_alloc_block now needs one more parameter(goal)
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,6 +39,7 @@
else()
#Generic example target
set(BLOCKDEV_TYPE linux)
+ add_definitions(-DCONFIG_EXTENT_FULL=1)
add_definitions(-DCONFIG_HAVE_OWN_OFLAGS=0)
add_definitions(-DCONFIG_HAVE_OWN_ERRNO=0)
add_definitions(-DCONFIG_HAVE_OWN_ASSERT=0)
--- a/lwext4/ext4.c
+++ b/lwext4/ext4.c
@@ -1255,8 +1255,8 @@
int ext4_fread(ext4_file *f, void *buf, size_t size, size_t *rcnt)
{
uint32_t u;
- uint32_t fblock;
- uint32_t fblock_start;
+ ext4_fsblk_t fblock;
+ ext4_fsblk_t fblock_start;
uint32_t fblock_cnt;
uint32_t sblock;
uint32_t sblock_end;
@@ -1419,13 +1419,13 @@
int ext4_fwrite(ext4_file *f, const void *buf, size_t size, size_t *wcnt)
{
uint32_t u;
- uint32_t fblock;
+ ext4_fsblk_t fblock;
uint32_t sblock;
uint32_t sblock_end;
uint32_t file_blocks;
uint32_t block_size;
- uint32_t fblock_start;
+ ext4_fsblk_t fblock_start;
uint32_t fblock_cnt;
struct ext4_block b;
@@ -1799,7 +1799,8 @@
{
struct ext4_block b;
struct ext4_inode_ref ref;
- uint32_t sblock, fblock;
+ uint32_t sblock;
+ ext4_fsblk_t fblock;
uint32_t block_size;
int r;
--- a/lwext4/ext4_balloc.c
+++ b/lwext4/ext4_balloc.c
@@ -53,9 +53,9 @@
* @return Block group index
*/
uint32_t ext4_balloc_get_bgid_of_block(struct ext4_sblock *s,
- uint32_t baddr)
+ uint64_t baddr)
{
- if (ext4_get32(s, first_data_block))
+ if (ext4_get32(s, first_data_block) && baddr)
baddr--;
return baddr / ext4_get32(s, blocks_per_group);
@@ -66,10 +66,10 @@
* @param bgid block group index
* @return Block address
*/
-uint32_t ext4_balloc_get_block_of_bgid(struct ext4_sblock *s,
+uint64_t ext4_balloc_get_block_of_bgid(struct ext4_sblock *s,
uint32_t bgid)
{
- uint32_t baddr = 0;
+ uint64_t baddr = 0;
if (ext4_get32(s, first_data_block))
baddr++;
@@ -77,7 +77,7 @@
return baddr;
}
-int ext4_balloc_free_block(struct ext4_inode_ref *inode_ref, uint32_t baddr)
+int ext4_balloc_free_block(struct ext4_inode_ref *inode_ref, ext4_fsblk_t baddr)
{
struct ext4_fs *fs = inode_ref->fs;
struct ext4_sblock *sb = &fs->sb;
@@ -92,7 +92,7 @@
return rc;
/* Load block with bitmap */
- uint32_t bitmap_block_addr =
+ ext4_fsblk_t bitmap_block_addr =
ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
struct ext4_block bitmap_block;
@@ -140,7 +140,7 @@
return ext4_fs_put_block_group_ref(&bg_ref);
}
-int ext4_balloc_free_blocks(struct ext4_inode_ref *inode_ref, uint32_t first,
+int ext4_balloc_free_blocks(struct ext4_inode_ref *inode_ref, ext4_fsblk_t first,
uint32_t count)
{
int rc = EOK;
@@ -175,7 +175,7 @@
ext4_fs_baddr2_index_in_group(sb, first);
/* Load block with bitmap */
- uint32_t bitmap_block_addr =
+ ext4_fsblk_t bitmap_block_addr =
ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
struct ext4_block bitmap_block;
@@ -242,97 +242,17 @@
return rc;
}
-/**@brief Compute 'goal' for allocation algorithm.
- * @param inode_ref Reference to inode, to allocate block for
- * @param goal
- * @return error code
- */
-static int ext4_balloc_find_goal(struct ext4_inode_ref *inode_ref,
- uint32_t *goal)
+int ext4_balloc_alloc_block(struct ext4_inode_ref *inode_ref,
+ ext4_fsblk_t goal,
+ ext4_fsblk_t *fblock)
{
- struct ext4_sblock *sb = &inode_ref->fs->sb;
- *goal = 0;
-
- uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
- uint32_t block_size = ext4_sb_get_block_size(sb);
- uint32_t inode_block_count = inode_size / block_size;
-
- if (inode_size % block_size != 0)
- inode_block_count++;
-
- /* If inode has some blocks, get last block address + 1 */
- if (inode_block_count > 0) {
- int rc = ext4_fs_get_inode_data_block_index(
- inode_ref, inode_block_count - 1, goal);
- if (rc != EOK)
- return rc;
-
- if (*goal != 0) {
- (*goal)++;
- return rc;
- }
-
- /* If goal == 0, sparse file -> continue */
- }
-
- /* Identify block group of inode */
-
- uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);
- uint32_t block_group = (inode_ref->index - 1) / inodes_per_group;
- block_size = ext4_sb_get_block_size(sb);
-
- /* Load block group reference */
- struct ext4_block_group_ref bg_ref;
- int rc =
- ext4_fs_get_block_group_ref(inode_ref->fs, block_group, &bg_ref);
- if (rc != EOK)
- return rc;
-
- /* Compute indexes */
- uint32_t block_group_count = ext4_block_group_cnt(sb);
- uint32_t inode_table_first_block =
- ext4_bg_get_inode_table_first_block(bg_ref.block_group, sb);
- uint16_t inode_table_item_size = ext4_get16(sb, inode_size);
- uint32_t inode_table_bytes;
-
- /* Check for last block group */
- if (block_group < block_group_count - 1) {
- inode_table_bytes = inodes_per_group * inode_table_item_size;
- } else {
- /* Last block group could be smaller */
- uint32_t inodes_count_total = ext4_get32(sb, inodes_count);
-
- inode_table_bytes =
- (inodes_count_total -
- ((block_group_count - 1) * inodes_per_group)) *
- inode_table_item_size;
- }
-
- uint32_t inode_table_blocks = inode_table_bytes / block_size;
-
- if (inode_table_bytes % block_size)
- inode_table_blocks++;
-
- *goal = inode_table_first_block + inode_table_blocks;
-
- return ext4_fs_put_block_group_ref(&bg_ref);
-}
-
-int ext4_balloc_alloc_block(struct ext4_inode_ref *inode_ref, uint32_t *fblock)
-{
- uint32_t allocated_block = 0;
- uint32_t bitmap_block_addr;
+ ext4_fsblk_t allocated_block = 0;
+ ext4_fsblk_t bitmap_block_addr;
uint32_t rel_block_idx = 0;
- uint32_t free_blocks;
- uint32_t goal;
+ uint64_t free_blocks;
struct ext4_block bitmap_block;
+ int rc;
- int rc = ext4_balloc_find_goal(inode_ref, &goal);
- if (rc != EOK) {
- /* no goal found => partition is full */
- return rc;
- }
-
struct ext4_sblock *sb = &inode_ref->fs->sb;
/* Load block group number for goal and relative index */
@@ -352,7 +272,7 @@
}
/* Compute indexes */
- uint32_t first_in_group = ext4_balloc_get_block_of_bgid(sb, bg_ref.index);
+ ext4_fsblk_t first_in_group = ext4_balloc_get_block_of_bgid(sb, bg_ref.index);
uint32_t first_in_group_index =
ext4_fs_baddr2_index_in_group(sb, first_in_group);
@@ -538,7 +458,7 @@
inode_ref->dirty = true;
/* Update block group free blocks count */
- uint32_t bg_free_blocks =
+ uint64_t bg_free_blocks =
ext4_bg_get_free_blocks_count(bg_ref.block_group, sb);
bg_free_blocks--;
ext4_bg_set_free_blocks_count(bg_ref.block_group, sb, bg_free_blocks);
@@ -552,7 +472,7 @@
}
int ext4_balloc_try_alloc_block(struct ext4_inode_ref *inode_ref,
- uint32_t baddr, bool *free)
+ ext4_fsblk_t baddr, bool *free)
{
int rc;
@@ -570,7 +490,7 @@
return rc;
/* Load block with bitmap */
- uint32_t bitmap_block_addr =
+ ext4_fsblk_t bitmap_block_addr =
ext4_bg_get_block_bitmap(bg_ref.block_group, sb);
struct ext4_block bitmap_block;
--- a/lwext4/ext4_balloc.h
+++ b/lwext4/ext4_balloc.h
@@ -54,7 +54,7 @@
* @return Block group index
*/
uint32_t ext4_balloc_get_bgid_of_block(struct ext4_sblock *s,
- uint32_t baddr);
+ ext4_fsblk_t baddr);
/**@brief Compute the starting block address of a block group
* @param sb superblock pointer.
@@ -61,7 +61,7 @@
* @param bgid block group index
* @return Block address
*/
-uint32_t ext4_balloc_get_block_of_bgid(struct ext4_sblock *s,
+ext4_fsblk_t ext4_balloc_get_block_of_bgid(struct ext4_sblock *s,
uint32_t bgid);
/**@brief Free block from inode.
@@ -68,20 +68,23 @@
* @param inode_ref inode reference
* @param baddr block address
* @return standard error code*/
-int ext4_balloc_free_block(struct ext4_inode_ref *inode_ref, uint32_t baddr);
+int ext4_balloc_free_block(struct ext4_inode_ref *inode_ref, ext4_fsblk_t baddr);
/**@brief Free blocks from inode.
* @param inode_ref inode reference
* @param baddr block address
* @return standard error code*/
-int ext4_balloc_free_blocks(struct ext4_inode_ref *inode_ref, uint32_t first,
+int ext4_balloc_free_blocks(struct ext4_inode_ref *inode_ref, ext4_fsblk_t first,
uint32_t count);
/**@brief Allocate block procedure.
* @param inode_ref inode reference
+ * @param goal
* @param baddr allocated block address
* @return standard error code*/
-int ext4_balloc_alloc_block(struct ext4_inode_ref *inode_ref, uint32_t *baddr);
+int ext4_balloc_alloc_block(struct ext4_inode_ref *inode_ref,
+ ext4_fsblk_t goal,
+ ext4_fsblk_t *baddr);
/**@brief Try allocate selected block.
* @param inode_ref inode reference
@@ -89,7 +92,7 @@
* @param free if baddr is not allocated
* @return standard error code*/
int ext4_balloc_try_alloc_block(struct ext4_inode_ref *inode_ref,
- uint32_t baddr, bool *free);
+ ext4_fsblk_t baddr, bool *free);
#endif /* EXT4_BALLOC_H_ */
--- a/lwext4/ext4_dir.c
+++ b/lwext4/ext4_dir.c
@@ -138,7 +138,7 @@
return rc;
}
- uint32_t next_block_phys_idx;
+ ext4_fsblk_t next_block_phys_idx;
int rc = ext4_fs_get_inode_data_block_index(
it->inode_ref, next_block_idx, &next_block_phys_idx);
if (rc != EOK)
@@ -262,7 +262,7 @@
/* Linear algorithm */
uint32_t iblock = 0;
- uint32_t fblock = 0;
+ ext4_fsblk_t fblock = 0;
uint32_t block_size = ext4_sb_get_block_size(&fs->sb);
uint32_t inode_size = ext4_inode_get_size(&fs->sb, parent->inode);
uint32_t total_blocks = inode_size / block_size;
@@ -352,7 +352,7 @@
/* Linear algorithm */
uint32_t iblock;
- uint32_t fblock;
+ ext4_fsblk_t fblock;
uint32_t block_size = ext4_sb_get_block_size(sb);
uint32_t inode_size = ext4_inode_get_size(sb, parent->inode);
uint32_t total_blocks = inode_size / block_size;
--- a/lwext4/ext4_dir_idx.c
+++ b/lwext4/ext4_dir_idx.c
@@ -207,7 +207,7 @@
int ext4_dir_dx_init(struct ext4_inode_ref *dir)
{
/* Load block 0, where will be index root located */
- uint32_t fblock;
+ ext4_fsblk_t fblock;
int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock);
if (rc != EOK)
return rc;
@@ -411,7 +411,7 @@
indirect_level--;
- uint32_t fblock;
+ ext4_fsblk_t fblock;
int rc = ext4_fs_get_inode_data_block_index(
inode_ref, next_block, &fblock);
if (rc != EOK)
@@ -487,7 +487,7 @@
/* Fill new path */
while (num_handles--) {
uint32_t block_idx = ext4_dir_dx_entry_get_block(p->position);
- uint32_t block_addr;
+ ext4_fsblk_t block_addr;
int rc = ext4_fs_get_inode_data_block_index(
inode_ref, block_idx, &block_addr);
@@ -520,7 +520,7 @@
const char *name)
{
/* Load direct block 0 (index root) */
- uint32_t root_block_addr;
+ ext4_fsblk_t root_block_addr;
int rc2;
int rc =
ext4_fs_get_inode_data_block_index(inode_ref, 0, &root_block_addr);
@@ -561,7 +561,7 @@
/* Load leaf block */
uint32_t leaf_block_idx =
ext4_dir_dx_entry_get_block(dx_block->position);
- uint32_t leaf_block_addr;
+ ext4_fsblk_t leaf_block_addr;
rc = ext4_fs_get_inode_data_block_index(
inode_ref, leaf_block_idx, &leaf_block_addr);
@@ -797,7 +797,7 @@
ext4_dir_dx_entry_comparator);
#endif
/* Allocate new block for store the second part of entries */
- uint32_t new_fblock;
+ ext4_fsblk_t new_fblock;
uint32_t new_iblock;
rc = ext4_fs_append_inode_block(inode_ref, &new_fblock, &new_iblock);
if (rc != EOK) {
@@ -938,7 +938,7 @@
return ENOSPC;
/* Add new block to directory */
- uint32_t new_fblock;
+ ext4_fsblk_t new_fblock;
uint32_t new_iblock;
int rc = ext4_fs_append_inode_block(inode_ref, &new_fblock,
&new_iblock);
@@ -1078,7 +1078,7 @@
int rc2 = EOK;
/* Get direct block 0 (index root) */
- uint32_t root_block_addr;
+ ext4_fsblk_t root_block_addr;
int rc =
ext4_fs_get_inode_data_block_index(parent, 0, &root_block_addr);
if (rc != EOK)
@@ -1118,7 +1118,7 @@
/* Try to insert to existing data block */
uint32_t leaf_block_idx =
ext4_dir_dx_entry_get_block(dx_block->position);
- uint32_t leaf_block_addr;
+ ext4_fsblk_t leaf_block_addr;
rc = ext4_fs_get_inode_data_block_index(parent, leaf_block_idx,
&leaf_block_addr);
if (rc != EOK)
@@ -1197,7 +1197,7 @@
uint32_t parent_inode)
{
/* Load block 0, where will be index root located */
- uint32_t fblock;
+ ext4_fsblk_t fblock;
int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock);
if (rc != EOK)
return rc;
--- a/lwext4/ext4_extent.c
+++ b/lwext4/ext4_extent.c
@@ -131,7 +131,7 @@
* @return Error code*/
static int
ext4_extent_find_block(struct ext4_inode_ref *inode_ref, uint32_t iblock,
- uint32_t *fblock)
+ ext4_fsblk_t *fblock)
{
int rc;
/* Compute bound defined by i-node size */
@@ -185,7 +185,7 @@
*fblock = 0;
} else {
/* Compute requested physical block address */
- uint32_t phys_block;
+ ext4_fsblk_t phys_block;
uint32_t first = ext4_extent_get_first_block(extent);
phys_block = ext4_extent_get_start(extent) + iblock - first;
@@ -313,7 +313,7 @@
static int ext4_extent_release_branch(struct ext4_inode_ref *inode_ref,
struct ext4_extent_index *index)
{
- uint32_t fblock = ext4_extent_index_get_leaf(index);
+ ext4_fsblk_t fblock = ext4_extent_index_get_leaf(index);
uint32_t i;
struct ext4_block block;
int rc = ext4_block_get(inode_ref->fs->bdev, &block, fblock);
@@ -377,7 +377,7 @@
/* First extent maybe released partially */
uint32_t first_iblock = ext4_extent_get_first_block(path_ptr->extent);
- uint32_t first_fblock = ext4_extent_get_start(path_ptr->extent) +
+ ext4_fsblk_t first_fblock = ext4_extent_get_start(path_ptr->extent) +
from - first_iblock;
uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);
@@ -527,11 +527,15 @@
if (entries == limit) {
/* Full node - allocate block for new one */
- uint32_t fblock;
- int rc = ext4_balloc_alloc_block(inode_ref, &fblock);
+ ext4_fsblk_t goal, fblock;
+ int rc = ext4_fs_indirect_find_goal(inode_ref, &goal);
if (rc != EOK)
return rc;
+ rc = ext4_balloc_alloc_block(inode_ref, goal, &fblock);
+ if (rc != EOK)
+ return rc;
+
struct ext4_block block;
rc =
ext4_block_get(inode_ref->fs->bdev, &block, fblock);
@@ -626,11 +630,15 @@
uint16_t limit = ext4_extent_header_get_max_entries_count(path->header);
if (entries == limit) {
- uint32_t new_fblock;
- int rc = ext4_balloc_alloc_block(inode_ref, &new_fblock);
+ ext4_fsblk_t goal, new_fblock;
+ int rc = ext4_fs_indirect_find_goal(inode_ref, &goal);
if (rc != EOK)
return rc;
+ rc = ext4_balloc_alloc_block(inode_ref, goal, &new_fblock);
+ if (rc != EOK)
+ return rc;
+
struct ext4_block block;
rc = ext4_block_get(inode_ref->fs->bdev, &block, new_fblock);
if (rc != EOK)
@@ -737,9 +745,10 @@
* @return Error code*/
static int
ext4_extent_append_block(struct ext4_inode_ref *inode_ref, uint32_t *iblock,
- uint32_t *fblock, bool update_size)
+ ext4_fsblk_t *fblock, bool update_size)
{
uint16_t i;
+ ext4_fsblk_t goal;
struct ext4_sblock *sb = &inode_ref->fs->sb;
uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
uint32_t block_size = ext4_sb_get_block_size(sb);
@@ -771,12 +780,16 @@
uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);
uint16_t block_limit = (1 << 15);
- uint32_t phys_block = 0;
+ ext4_fsblk_t phys_block = 0;
if (block_count < block_limit) {
/* There is space for new block in the extent */
if (block_count == 0) {
+ int rc = ext4_fs_indirect_find_goal(inode_ref, &goal);
+ if (rc != EOK)
+ goto finish;
+
/* Existing extent is empty */
- rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
+ rc = ext4_balloc_alloc_block(inode_ref, goal, &phys_block);
if (rc != EOK)
goto finish;
@@ -798,6 +811,11 @@
goto finish;
} else {
+ ext4_fsblk_t goal;
+ int rc = ext4_fs_indirect_find_goal(inode_ref, &goal);
+ if (rc != EOK)
+ goto finish;
+
/* Existing extent contains some blocks */
phys_block = ext4_extent_get_start(path_ptr->extent);
phys_block +=
@@ -840,8 +858,12 @@
/* Append new extent to the tree */
phys_block = 0;
+ rc = ext4_fs_indirect_find_goal(inode_ref, &goal);
+ if (rc != EOK)
+ goto finish;
+
/* Allocate new data block */
- rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
+ rc = ext4_balloc_alloc_block(inode_ref, goal, &phys_block);
if (rc != EOK)
goto finish;
@@ -893,11 +915,11 @@
}
int ext4_extent_get_blocks(struct ext4_inode_ref *inode_ref, ext4_fsblk_t iblock,
- uint32_t max_blocks, ext4_fsblk_t *result, bool create,
- uint32_t *blocks_count)
+ ext4_lblk_t max_blocks, ext4_fsblk_t *result, bool create,
+ ext4_lblk_t *blocks_count)
{
uint32_t iblk = iblock;
- uint32_t fblk = 0;
+ ext4_fsblk_t fblk = 0;
int r;
if (blocks_count)
--- a/lwext4/ext4_extent_full.c
+++ b/lwext4/ext4_extent_full.c
@@ -28,6 +28,7 @@
#include "ext4_config.h"
#include "ext4_blockdev.h"
+#include "ext4_fs.h"
#include "ext4_super.h"
#include "ext4_balloc.h"
#include "ext4_debug.h"
@@ -144,10 +145,10 @@
}
static int ext4_allocate_single_block(struct ext4_inode_ref *inode_ref,
- ext4_fsblk_t goal __unused,
+ ext4_fsblk_t goal,
ext4_fsblk_t *blockp)
{
- return ext4_balloc_alloc_block(inode_ref, (uint32_t *)blockp);
+ return ext4_balloc_alloc_block(inode_ref, goal, blockp);
}
static ext4_fsblk_t ext4_new_meta_blocks(struct ext4_inode_ref *inode_ref,
@@ -167,9 +168,7 @@
ext4_fsblk_t block, uint32_t count,
uint32_t flags __unused)
{
- uint32_t i;
- for (i = 0; i < count; i++)
- ext4_balloc_free_block(inode_ref, (uint32_t)block + i);
+ ext4_balloc_free_blocks(inode_ref, block, count);
}
static size_t ext4_ext_space_block(struct ext4_inode_ref *inode_ref)
@@ -232,7 +231,8 @@
return max;
}
-static ext4_fsblk_t ext4_ext_find_goal(struct ext4_extent_path *path,
+static ext4_fsblk_t ext4_ext_find_goal(struct ext4_inode_ref *inode_ref,
+ struct ext4_extent_path *path,
ext4_lblk_t block)
{
if (path) {
@@ -274,7 +274,7 @@
}
/* OK. use inode's group */
- return 0;
+ return ext4_fs_inode_to_goal_block(inode_ref);
}
/*
@@ -287,7 +287,7 @@
{
ext4_fsblk_t goal, newblock;
- goal = ext4_ext_find_goal(path, to_le32(ex->first_block));
+ goal = ext4_ext_find_goal(inode_ref, path, to_le32(ex->first_block));
newblock = ext4_new_meta_blocks(inode_ref, goal, flags, NULL, err);
return newblock;
}
@@ -1054,7 +1054,7 @@
goal = ext4_idx_pblock(
EXT_FIRST_INDEX(ext_inode_hdr(inode_ref->inode)));
else
- goal = 0;
+ goal = ext4_fs_inode_to_goal_block(inode_ref);
newblock = ext4_new_meta_blocks(inode_ref, goal, flags, NULL, &err);
if (newblock == 0)
@@ -1714,7 +1714,7 @@
allocated = max_blocks;
/* allocate new block */
- goal = ext4_ext_find_goal(path, iblock);
+ goal = ext4_ext_find_goal(inode_ref, path, iblock);
newblock = ext4_new_meta_blocks(inode_ref, goal, 0, &allocated, &err);
if (!newblock)
goto out2;
--- a/lwext4/ext4_fs.c
+++ b/lwext4/ext4_fs.c
@@ -245,7 +245,7 @@
* @return Error code
*/
static int ext4_block_in_group(struct ext4_sblock *s,
- uint32_t baddr,
+ ext4_fsblk_t baddr,
uint32_t bgid)
{
uint32_t actual_bgid;
@@ -284,14 +284,14 @@
uint16_t inode_size = ext4_get16(&bg_ref->fs->sb, inode_size);
uint32_t block_size = ext4_sb_get_block_size(&bg_ref->fs->sb);
uint32_t inodes_per_group = ext4_get32(&bg_ref->fs->sb, inodes_per_group);
- uint32_t bitmap_block_addr =
+ ext4_fsblk_t bitmap_block_addr =
ext4_bg_get_block_bitmap(bg_ref->block_group, &bg_ref->fs->sb);
- uint32_t bitmap_inode_addr =
+ ext4_fsblk_t bitmap_inode_addr =
ext4_bg_get_inode_bitmap(bg_ref->block_group, &bg_ref->fs->sb);
- uint32_t inode_table_addr =
+ ext4_fsblk_t inode_table_addr =
ext4_bg_get_inode_table_first_block(bg_ref->block_group,
&bg_ref->fs->sb);
- uint32_t first_group_addr =
+ ext4_fsblk_t first_group_addr =
ext4_balloc_get_block_of_bgid(&bg_ref->fs->sb, bg_ref->index);
uint32_t dsc_per_block =
@@ -384,7 +384,7 @@
static int ext4_fs_init_inode_bitmap(struct ext4_block_group_ref *bg_ref)
{
/* Load bitmap */
- uint32_t bitmap_block_addr =
+ ext4_fsblk_t bitmap_block_addr =
ext4_bg_get_inode_bitmap(bg_ref->block_group, &bg_ref->fs->sb);
struct ext4_block block_bitmap;
@@ -429,16 +429,16 @@
uint32_t inodes_per_block = block_size / inode_size;
uint32_t inodes_in_group = ext4_inodes_in_group_cnt(sb, bg_ref->index);
uint32_t table_blocks = inodes_in_group / inodes_per_block;
- uint32_t fblock;
+ ext4_fsblk_t fblock;
if (inodes_in_group % inodes_per_block)
table_blocks++;
/* Compute initialization bounds */
- uint32_t first_block =
+ ext4_fsblk_t first_block =
ext4_bg_get_inode_table_first_block(bg_ref->block_group, sb);
- uint32_t last_block = first_block + table_blocks - 1;
+ ext4_fsblk_t last_block = first_block + table_blocks - 1;
/* Initialization of all itable blocks */
for (fblock = first_block; fblock <= last_block; ++fblock) {
@@ -459,7 +459,7 @@
return EOK;
}
-static uint64_t ext4_fs_get_descriptor_block(struct ext4_sblock *s,
+static ext4_fsblk_t ext4_fs_get_descriptor_block(struct ext4_sblock *s,
uint32_t bgid,
uint32_t dsc_per_block)
{
@@ -649,7 +649,7 @@
uint32_t byte_offset_in_group = offset_in_group * inode_size;
/* Compute block address */
- uint64_t block_id =
+ ext4_fsblk_t block_id =
inode_table_start + (byte_offset_in_group / block_size);
rc = ext4_block_get(fs->bdev, &ref->block, block_id);
@@ -807,7 +807,7 @@
/* Release all indirect (no data) blocks */
/* 1) Single indirect */
- uint32_t fblock = ext4_inode_get_indirect_block(inode_ref->inode, 0);
+ ext4_fsblk_t fblock = ext4_inode_get_indirect_block(inode_ref->inode, 0);
if (fblock != 0) {
int rc = ext4_balloc_free_block(inode_ref, fblock);
if (rc != EOK)
@@ -828,7 +828,7 @@
if (rc != EOK)
return rc;
- uint32_t ind_block;
+ ext4_fsblk_t ind_block;
for (offset = 0; offset < count; ++offset) {
ind_block = to_le32(((uint32_t *)block.data)[offset]);
@@ -859,7 +859,7 @@
if (rc != EOK)
return rc;
- uint32_t ind_block;
+ ext4_fsblk_t ind_block;
for (offset = 0; offset < count; ++offset) {
ind_block = to_le32(((uint32_t *)block.data)[offset]);
@@ -872,7 +872,7 @@
return rc;
}
- uint32_t ind_subblk;
+ ext4_fsblk_t ind_subblk;
for (suboff = 0; suboff < count; ++suboff) {
ind_subblk = to_le32(((uint32_t *)subblock.data)[suboff]);
@@ -909,7 +909,7 @@
inode_ref->dirty = true;
/* Free block with extended attributes if present */
- uint32_t xattr_block =
+ ext4_fsblk_t xattr_block =
ext4_inode_get_file_acl(inode_ref->inode, &fs->sb);
if (xattr_block) {
int rc = ext4_balloc_free_block(inode_ref, xattr_block);
@@ -1001,8 +1001,95 @@
return EOK;
}
+/**@brief Compute 'goal' for inode index
+ * @param inode_ref Reference to inode, to allocate block for
+ * @return goal
+ */
+ext4_fsblk_t ext4_fs_inode_to_goal_block(struct ext4_inode_ref *inode_ref)
+{
+ uint32_t group_inodes =
+ ext4_get32(&inode_ref->fs->sb, inodes_per_group);
+ return (inode_ref->index - 1) / group_inodes;
+}
+
+/**@brief Compute 'goal' for allocation algorithm (For blockmap).
+ * @param inode_ref Reference to inode, to allocate block for
+ * @param goal
+ * @return error code
+ */
+int ext4_fs_indirect_find_goal(struct ext4_inode_ref *inode_ref,
+ ext4_fsblk_t *goal)
+{
+ struct ext4_sblock *sb = &inode_ref->fs->sb;
+ *goal = 0;
+
+ uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
+ uint32_t block_size = ext4_sb_get_block_size(sb);
+ uint32_t inode_block_count = inode_size / block_size;
+
+ if (inode_size % block_size != 0)
+ inode_block_count++;
+
+ /* If inode has some blocks, get last block address + 1 */
+ if (inode_block_count > 0) {
+ int rc = ext4_fs_get_inode_data_block_index(
+ inode_ref, inode_block_count - 1, goal);
+ if (rc != EOK)
+ return rc;
+
+ if (*goal != 0) {
+ (*goal)++;
+ return rc;
+ }
+
+ /* If goal == 0, sparse file -> continue */
+ }
+
+ /* Identify block group of inode */
+
+ uint32_t inodes_per_group = ext4_get32(sb, inodes_per_group);
+ uint32_t block_group = (inode_ref->index - 1) / inodes_per_group;
+ block_size = ext4_sb_get_block_size(sb);
+
+ /* Load block group reference */
+ struct ext4_block_group_ref bg_ref;
+ int rc =
+ ext4_fs_get_block_group_ref(inode_ref->fs, block_group, &bg_ref);
+ if (rc != EOK)
+ return rc;
+
+ /* Compute indexes */
+ uint32_t block_group_count = ext4_block_group_cnt(sb);
+ ext4_fsblk_t inode_table_first_block =
+ ext4_bg_get_inode_table_first_block(bg_ref.block_group, sb);
+ uint16_t inode_table_item_size = ext4_get16(sb, inode_size);
+ uint32_t inode_table_bytes;
+
+ /* Check for last block group */
+ if (block_group < block_group_count - 1) {
+ inode_table_bytes = inodes_per_group * inode_table_item_size;
+ } else {
+ /* Last block group could be smaller */
+ uint32_t inodes_count_total = ext4_get32(sb, inodes_count);
+
+ inode_table_bytes =
+ (inodes_count_total -
+ ((block_group_count - 1) * inodes_per_group)) *
+ inode_table_item_size;
+ }
+
+ ext4_fsblk_t inode_table_blocks = inode_table_bytes / block_size;
+
+ if (inode_table_bytes % block_size)
+ inode_table_blocks++;
+
+ *goal = inode_table_first_block + inode_table_blocks;
+
+ return ext4_fs_put_block_group_ref(&bg_ref);
+}
+
static int ext4_fs_get_inode_data_block_idx(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t *fblock,
+ uint64_t iblock, ext4_fsblk_t *fblock,
bool extent_create)
{
struct ext4_fs *fs = inode_ref->fs;
@@ -1013,7 +1100,7 @@
return EOK;
}
- uint32_t current_block;
+ ext4_fsblk_t current_block;
(void)extent_create;
#if CONFIG_EXTENT_ENABLE
@@ -1028,7 +1115,7 @@
if (rc != EOK)
return rc;
- current_block = (uint32_t)current_fsblk;
+ current_block = current_fsblk;
*fblock = current_block;
ext4_assert(*fblock);
@@ -1120,7 +1207,7 @@
int ext4_fs_get_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t *fblock)
+ uint64_t iblock, ext4_fsblk_t *fblock)
{
return ext4_fs_get_inode_data_block_idx(inode_ref, iblock, fblock,
false);
@@ -1127,7 +1214,7 @@
}
int ext4_fs_init_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t *fblock)
+ uint64_t iblock, ext4_fsblk_t *fblock)
{
return ext4_fs_get_inode_data_block_idx(inode_ref, iblock, fblock,
true);
@@ -1134,7 +1221,7 @@
}
int ext4_fs_set_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t fblock)
+ uint64_t iblock, ext4_fsblk_t fblock)
{
struct ext4_fs *fs = inode_ref->fs;
@@ -1151,7 +1238,7 @@
/* Handle simple case when we are dealing with direct reference */
if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) {
ext4_inode_set_direct_block(inode_ref->inode, (uint32_t)iblock,
- fblock);
+ (uint32_t)fblock);
inode_ref->dirty = true;
return EOK;
@@ -1175,12 +1262,12 @@
/* Compute offsets for the topmost level */
uint64_t block_offset_in_level =
iblock - fs->inode_block_limits[level - 1];
- uint32_t current_block =
+ ext4_fsblk_t current_block =
ext4_inode_get_indirect_block(inode_ref->inode, level - 1);
uint32_t offset_in_block =
block_offset_in_level / fs->inode_blocks_per_level[level - 1];
- uint32_t new_block_addr;
+ ext4_fsblk_t new_block_addr;
struct ext4_block block;
struct ext4_block new_block;
@@ -1188,13 +1275,20 @@
/* Is needed to allocate indirect block on the i-node level */
if (current_block == 0) {
/* Allocate new indirect block */
- int rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr);
+ ext4_fsblk_t goal;
+ int rc = ext4_fs_indirect_find_goal(inode_ref, &goal);
if (rc != EOK)
return rc;
+ rc = ext4_balloc_alloc_block(inode_ref,
+ goal,
+ &new_block_addr);
+ if (rc != EOK)
+ return rc;
+
/* Update i-node */
ext4_inode_set_indirect_block(inode_ref->inode, level - 1,
- new_block_addr);
+ (uint32_t)new_block_addr);
inode_ref->dirty = true;
/* Load newly allocated block */
@@ -1229,9 +1323,16 @@
to_le32(((uint32_t *)block.data)[offset_in_block]);
if ((level > 1) && (current_block == 0)) {
+ ext4_fsblk_t goal;
+ rc = ext4_fs_indirect_find_goal(inode_ref, &goal);
+ if (rc != EOK) {
+ ext4_block_set(fs->bdev, &block);
+ return rc;
+ }
+
/* Allocate new block */
rc =
- ext4_balloc_alloc_block(inode_ref, &new_block_addr);
+ ext4_balloc_alloc_block(inode_ref, goal, &new_block_addr);
if (rc != EOK) {
ext4_block_set(fs->bdev, &block);
return rc;
@@ -1258,7 +1359,7 @@
/* Write block address to the parent */
((uint32_t *)block.data)[offset_in_block] =
- to_le32(new_block_addr);
+ to_le32((uint32_t)new_block_addr);
block.dirty = true;
current_block = new_block_addr;
}
@@ -1266,7 +1367,7 @@
/* Will be finished, write the fblock address */
if (level == 1) {
((uint32_t *)block.data)[offset_in_block] =
- to_le32(fblock);
+ to_le32((uint32_t)fblock);
block.dirty = true;
}
@@ -1295,7 +1396,7 @@
int ext4_fs_release_inode_block(struct ext4_inode_ref *inode_ref,
uint32_t iblock)
{
- uint32_t fblock;
+ ext4_fsblk_t fblock;
struct ext4_fs *fs = inode_ref->fs;
@@ -1336,7 +1437,7 @@
/* Compute offsets for the topmost level */
uint64_t block_offset_in_level =
iblock - fs->inode_block_limits[level - 1];
- uint32_t current_block =
+ ext4_fsblk_t current_block =
ext4_inode_get_indirect_block(inode, level - 1);
uint32_t offset_in_block =
block_offset_in_level / fs->inode_blocks_per_level[level - 1];
@@ -1394,7 +1495,7 @@
}
int ext4_fs_append_inode_block(struct ext4_inode_ref *inode_ref,
- uint32_t *fblock, uint32_t *iblock)
+ ext4_fsblk_t *fblock, uint32_t *iblock)
{
#if CONFIG_EXTENT_ENABLE
/* Handle extents separately */
@@ -1438,8 +1539,12 @@
uint32_t new_block_idx = inode_size / block_size;
/* Allocate new physical block */
- uint32_t phys_block;
- int rc = ext4_balloc_alloc_block(inode_ref, &phys_block);
+ ext4_fsblk_t goal, phys_block;
+ int rc = ext4_fs_indirect_find_goal(inode_ref, &goal);
+ if (rc != EOK)
+ return rc;
+
+ rc = ext4_balloc_alloc_block(inode_ref, goal, &phys_block);
if (rc != EOK)
return rc;
--- a/lwext4/ext4_fs.h
+++ b/lwext4/ext4_fs.h
@@ -54,7 +54,7 @@
* @return Relative number of block
*/
static inline uint32_t ext4_fs_baddr2_index_in_group(struct ext4_sblock *s,
- uint32_t baddr)
+ ext4_fsblk_t baddr)
{
if (ext4_get32(s, first_data_block))
baddr--;
@@ -68,7 +68,7 @@
* @param bgid Block group
* @return Absolute block address
*/
-static inline uint32_t ext4_fs_index_in_group2_baddr(struct ext4_sblock *s,
+static inline ext4_fsblk_t ext4_fs_index_in_group2_baddr(struct ext4_sblock *s,
uint32_t index,
uint32_t bgid)
{
@@ -79,7 +79,7 @@
}
/**@brief TODO: */
-static inline uint64_t ext4_fs_first_bg_block_no(struct ext4_sblock *s,
+static inline ext4_fsblk_t ext4_fs_first_bg_block_no(struct ext4_sblock *s,
uint32_t bgid)
{
return (uint64_t)bgid * ext4_get32(s, blocks_per_group) +
@@ -167,6 +167,20 @@
*/
int ext4_fs_truncate_inode(struct ext4_inode_ref *inode_ref, uint64_t new_size);
+/**@brief Compute 'goal' for inode index
+ * @param inode_ref Reference to inode, to allocate block for
+ * @return goal
+ */
+ext4_fsblk_t ext4_fs_inode_to_goal_block(struct ext4_inode_ref *inode_ref);
+
+/**@brief Compute 'goal' for allocation algorithm (For blockmap).
+ * @param inode_ref Reference to inode, to allocate block for
+ * @param goal
+ * @return error code
+ */
+int ext4_fs_indirect_find_goal(struct ext4_inode_ref *inode_ref,
+ ext4_fsblk_t *goal);
+
/**@brief Get physical block address by logical index of the block.
* @param inode_ref I-node to read block address from
* @param iblock Logical index of block
@@ -174,7 +188,7 @@
* @return Error code
*/
int ext4_fs_get_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t *fblock);
+ uint64_t iblock, ext4_fsblk_t *fblock);
/**@brief Initialize a part of unwritten range of the inode.
* @param inode_ref I-node to proceed on.
@@ -183,7 +197,7 @@
* @return Error code
*/
int ext4_fs_init_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t *fblock);
+ uint64_t iblock, ext4_fsblk_t *fblock);
/**@brief Set physical block address for the block logical address into the
* i-node.
@@ -193,7 +207,7 @@
* @return Error code
*/
int ext4_fs_set_inode_data_block_index(struct ext4_inode_ref *inode_ref,
- uint64_t iblock, uint32_t fblock);
+ uint64_t iblock, ext4_fsblk_t fblock);
/**@brief Release data block from i-node
* @param inode_ref I-node to release block from
@@ -210,7 +224,7 @@
* @return Error code
*/
int ext4_fs_append_inode_block(struct ext4_inode_ref *inode_ref,
- uint32_t *fblock, uint32_t *iblock);
+ ext4_fsblk_t *fblock, uint32_t *iblock);
/**@brief Increment inode link count.
* @param inode none handle
--- a/lwext4/ext4_xattr.c
+++ b/lwext4/ext4_xattr.c
@@ -44,7 +44,6 @@
#include "ext4_block_group.h"
#include "ext4_balloc.h"
#include "ext4_inode.h"
-#include "ext4_extent.h"
#include <string.h>
#include <stdlib.h>
@@ -466,12 +465,16 @@
{
int ret = EOK;
- uint64_t xattr_block = 0;
+ ext4_fsblk_t xattr_block = 0;
xattr_block = ext4_inode_get_file_acl(xattr_ref->inode_ref->inode,
&xattr_ref->fs->sb);
if (!xattr_block) {
+ ext4_fsblk_t goal =
+ ext4_fs_inode_to_goal_block(xattr_ref->inode_ref);
+
ret = ext4_balloc_alloc_block(xattr_ref->inode_ref,
- (uint32_t *)&xattr_block);
+ goal,
+ &xattr_block);
if (ret != EOK)
goto Finish;
@@ -495,7 +498,7 @@
static void ext4_xattr_try_free_block(struct ext4_xattr_ref *xattr_ref)
{
- uint64_t xattr_block;
+ ext4_fsblk_t xattr_block;
xattr_block = ext4_inode_get_file_acl(xattr_ref->inode_ref->inode,
&xattr_ref->fs->sb);
ext4_inode_set_file_acl(xattr_ref->inode_ref->inode, &xattr_ref->fs->sb,
@@ -760,7 +763,7 @@
struct ext4_xattr_ref *ref)
{
int rc;
- uint64_t xattr_block;
+ ext4_fsblk_t xattr_block;
xattr_block = ext4_inode_get_file_acl(inode_ref->inode, &fs->sb);
RB_INIT(&ref->root);
ref->ea_size = 0;