shithub: lwext4

Download patch

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;