Index: uspace/lib/ext4/libext4_extent.c
===================================================================
--- uspace/lib/ext4/libext4_extent.c	(revision 96606fe85ef15212d997e4ef8df25a495215a6c9)
+++ uspace/lib/ext4/libext4_extent.c	(revision 5d3d75a5fab53c5dc6cff519a20ca66c91c68b0f)
@@ -739,115 +739,19 @@
  */
 static int ext4_extent_append_extent(ext4_inode_ref_t *inode_ref,
-		ext4_extent_path_t *path, ext4_extent_path_t **last_path_item,
-		uint32_t iblock)
+		ext4_extent_path_t *path, uint32_t iblock)
 {
 
 	int rc;
 
-	ext4_extent_path_t *path_ptr = *last_path_item;
+	ext4_extent_path_t *path_ptr = path + path->depth;
 
 	uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header);
 	uint16_t limit = ext4_extent_header_get_max_entries_count(path_ptr->header);
 
-	/* Trivial way - no splitting */
-//	if ((entries < limit) && (path == path_ptr)) {
-//
-//		ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);
-//		path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries;
-//		path_ptr->block->dirty = true;
-//
-//		return EOK;
-//	}
-
 	uint32_t block_size =
 			ext4_superblock_get_block_size(inode_ref->fs->superblock);
 
-//	/* Trivial tree - grow (extents were in root node) */
-//	if ((path_ptr == path) && ((entries == limit))){
-//
-//		EXT4FS_DBG("splitting root with extents");
-//
-//		uint32_t new_fblock;
-//		rc = ext4_balloc_alloc_block(inode_ref, &new_fblock);
-//		if (rc != EOK) {
-//			EXT4FS_DBG("error in block allocation");
-//			return rc;
-//		}
-//
-////		EXT4FS_DBG("alllocated block \%u for new leaf", new_fblock);
-//
-//		block_t *block;
-//		rc = block_get(&block, inode_ref->fs->device,
-//				new_fblock, BLOCK_FLAGS_NOREAD);
-//		if (rc != EOK) {
-//			EXT4FS_DBG("error in block_get");
-//			return rc;
-//		}
-//
-//		memset(block->data, 0, block_size);
-//
-//		/* Move data from root to the new block */
-//		memcpy(block->data, inode_ref->inode->blocks,
-//				EXT4_INODE_BLOCKS * sizeof(uint32_t));
-//
-//		path_ptr++;
-//		path_ptr->block = block;
-//		path_ptr->header = (ext4_extent_header_t *)block->data;
-//		path_ptr->depth = 0;
-//		path_ptr->index = NULL;
-//
-//		uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header);
-//		path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries;
-//		ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);
-//		uint16_t limit = (block_size - sizeof(ext4_extent_header_t)) /
-//				sizeof(ext4_extent_t);
-//		ext4_extent_header_set_max_entries_count(path_ptr->header, limit);
-//
-//		/* Modify root (in inode) */
-//		path->depth = 1;
-//		path->extent = NULL;
-//		path->index = EXT4_EXTENT_FIRST_INDEX(path->header);
-//
-//		ext4_extent_header_set_depth(path->header, 1);
-//		ext4_extent_header_set_entries_count(path->header, 1);
-//
-//		ext4_extent_index_set_first_block(path->index, 0);
-//		ext4_extent_index_set_leaf(path->index, new_fblock);
-//
-//		path_ptr->block->dirty = true;
-//		path->block->dirty = true;
-//
-//		*last_path_item = path_ptr;
-//
-////		ext4_extent_header_t *tmp_root = path->header;
-////		EXT4FS_DBG("new root: items = \%u, maximum = \%u, depth = \%u", ext4_extent_header_get_entries_count(tmp_root),
-////				ext4_extent_header_get_max_entries_count(tmp_root), ext4_extent_header_get_depth(tmp_root));
-////
-////		ext4_extent_index_t *root_idx = EXT4_EXTENT_FIRST_INDEX(path->header);
-////		EXT4FS_DBG("first iblock = \%u, fblock = \%u", ext4_extent_index_get_first_block(root_idx),
-////				(uint32_t)ext4_extent_index_get_leaf(root_idx));
-////
-////		ext4_extent_header_t *new_leaf = path_ptr->header;
-////		EXT4FS_DBG("new leaf: items = \%u, maximum = \%u, depth = \%u", ext4_extent_header_get_entries_count(new_leaf),
-////				ext4_extent_header_get_max_entries_count(new_leaf), ext4_extent_header_get_depth(new_leaf));
-////
-////		for (uint32_t j = 0; j < ext4_extent_header_get_entries_count(new_leaf); ++j) {
-////			ext4_extent_t *tmp_ext = EXT4_EXTENT_FIRST(path_ptr->header) + j;
-////
-////			EXT4FS_DBG("item \%u, first iblock = \%u", j, ext4_extent_get_first_block(tmp_ext));
-////		}
-//
-//		EXT4FS_DBG("Root block containing extents was split");
-//		return EOK;
-//	}
-
-	// TODO !!!
-//	assert(false);
-
-//	EXT4FS_DBG("More complex splitting");
-
 	/* Start splitting */
 	while (path_ptr > path) {
-		uint32_t fblock;
 
 		entries = ext4_extent_header_get_entries_count(path_ptr->header);
@@ -858,5 +762,6 @@
 			EXT4FS_DBG("Full non-root node (\%s)", path_ptr->depth ? "index" : "extent");
 
-			/* Full node */
+			/* Full node - allocate block for new one */
+			uint32_t fblock;
 			rc = ext4_balloc_alloc_block(inode_ref, &fblock);
 			if (rc != EOK) {
@@ -871,12 +776,13 @@
 			}
 
-			/* Init block */
+			/* Put back not modified old block */
+			block_put(path_ptr->block);
+
+			/* Initialize newly allocated block and remember it */
 			memset(block->data, 0, block_size);
-
-			/* Not modified old block */
-			block_put(path_ptr->block);
 			path_ptr->block = block;
+
+			/* Update pointers in extent path structure */
 			path_ptr->header = block->data;
-
 			if (path_ptr->depth) {
 				path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header);
@@ -897,4 +803,5 @@
 			path_ptr->block->dirty = true;
 
+			/* Jump to the preceeding item */
 			path_ptr--;
 
@@ -915,10 +822,13 @@
 			ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);
 			path_ptr->block->dirty = true;
-			*last_path_item = path_ptr;
-
+
+			/* No more splitting needed */
 			return EOK;
 		}
 
 	}
+
+	assert(path_ptr == path);
+	// TODO condition is redundant here
 
 	/* Should be the root split too? */
@@ -947,4 +857,5 @@
 			}
 
+			/* Initialize newly allocated block */
 			memset(block->data, 0, block_size);
 
@@ -953,15 +864,44 @@
 					EXT4_INODE_BLOCKS * sizeof(uint32_t));
 
-			EXT4FS_DBG("New block prepared");
+			ext4_extent_header_t *dbg_header = block->data;
+			EXT4FS_DBG("old root: items = \%u, depth = \%u", ext4_extent_header_get_entries_count(dbg_header), ext4_extent_header_get_depth(dbg_header));
+
+			if (ext4_extent_header_get_depth(dbg_header)) {
+				for (uint16_t x = 0; x < ext4_extent_header_get_entries_count(dbg_header); ++x) {
+					ext4_extent_index_t *iii = EXT4_EXTENT_FIRST_INDEX(dbg_header) + x;
+					EXT4FS_DBG("root item \%u, iblock = \%u, leaf = \%u", x, ext4_extent_index_get_first_block(iii), (uint32_t)ext4_extent_index_get_leaf(iii));
+				}
+			} else {
+				for (uint16_t x = 0; x < ext4_extent_header_get_entries_count(dbg_header); ++x) {
+					ext4_extent_t *iii = EXT4_EXTENT_FIRST(dbg_header) + x;
+					EXT4FS_DBG("root item \%u, iblock = \%u, leaf = \%u, count = \%u", x, ext4_extent_get_first_block(iii), (uint32_t)ext4_extent_get_start(iii), ext4_extent_get_block_count(iii));
+				}
+			}
 
 			/* Make space for tree growing */
-			memmove(path + 1, path, path->depth + 1);
-
-			EXT4FS_DBG("Place for new root ready");
-
 			path_ptr = path + 1;
+			size_t bytes = (path->depth + 1) * sizeof(ext4_extent_path_t);
+			memmove(path_ptr, path, bytes);
+
+			/* Initialize new root metadata */
+			path->block = path_ptr->block;
+			path->header = path_ptr->header;
+			path->depth = path_ptr->depth + 1;
+			path->extent = NULL;
+			path->index = EXT4_EXTENT_FIRST_INDEX(path->header);
+
+			ext4_extent_header_set_entries_count(path->header, 1);
+			ext4_extent_header_set_depth(path->header, path->depth);
+			ext4_extent_index_set_first_block(path->index, 0);
+			ext4_extent_index_set_leaf(path->index, new_fblock);
+
+			path->block->dirty = true;
+
+
+			/* Switch storage for "old root" */
 			path_ptr->block = block;
 			path_ptr->header = (ext4_extent_header_t *)block->data;
 
+			/* Add new entry to the "old root" */
 			if (path_ptr->depth) {
 				limit = (block_size - sizeof(ext4_extent_header_t)) /
@@ -978,5 +918,4 @@
 				path_ptr->index = NULL;
 			}
-
 			ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);
 			ext4_extent_header_set_max_entries_count(path_ptr->header, limit);
@@ -984,22 +923,11 @@
 			path_ptr->block->dirty = true;
 
-			path->block = inode_ref->block;
-			path->depth = path_ptr->depth + 1;
-			path->header = (ext4_extent_header_t *)inode_ref->inode->blocks;
-			path->extent = NULL;
-			path->index = EXT4_EXTENT_FIRST_INDEX(path->header);
-
-
-			ext4_extent_header_set_entries_count(path->header, 1);
-			ext4_extent_header_set_depth(path->header, path->depth);
-
-			ext4_extent_index_set_first_block(path->index, 0);
-			ext4_extent_index_set_leaf(path->index, new_fblock);
-
-			path->block->dirty = true;
-
-			*last_path_item = *last_path_item + 1;
-
-			EXT4FS_DBG("Leaving split root");
+
+			EXT4FS_DBG("new root: items = \%u, depth = \%u, tmp depth = \%u", ext4_extent_header_get_entries_count(path->header), ext4_extent_header_get_depth(path->header), path->depth);
+
+			for (uint16_t x = 0; x < ext4_extent_header_get_entries_count(path->header); ++x) {
+				ext4_extent_index_t *iii = EXT4_EXTENT_FIRST_INDEX(path->header) + x;
+				EXT4FS_DBG("root item \%u, iblock = \%u, leaf = \%u", x, ext4_extent_index_get_first_block(iii), (uint32_t)ext4_extent_index_get_leaf(iii));
+			}
 
 		} else {
@@ -1007,14 +935,14 @@
 			EXT4FS_DBG("Adding entry to root node");
 
-			if (path_ptr->depth) {
-				path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries;
-				ext4_extent_index_set_first_block(path_ptr->index, iblock);
-				ext4_extent_index_set_leaf(path_ptr->index, (path_ptr + 1)->block->lba);
+			if (path->depth) {
+				path->index = EXT4_EXTENT_FIRST_INDEX(path->header) + entries;
+				ext4_extent_index_set_first_block(path->index, iblock);
+				ext4_extent_index_set_leaf(path->index, (path + 1)->block->lba);
 			} else {
-				path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries;
-				ext4_extent_set_first_block(path_ptr->extent, iblock);
-			}
-
-			ext4_extent_header_set_entries_count(path_ptr->header, entries + 1);
+				path->extent = EXT4_EXTENT_FIRST(path->header) + entries;
+				ext4_extent_set_first_block(path->extent, iblock);
+			}
+
+			ext4_extent_header_set_entries_count(path->header, entries + 1);
 			path->block->dirty = true;
 		}
@@ -1030,5 +958,5 @@
  * to some existing extent or creates new extents.
  * It includes possible extent tree modifications (splitting).
- *
+ *<
  * @param inode_ref			i-node to append block to
  * @param iblock			output logical number of newly allocated block
@@ -1151,9 +1079,14 @@
 
 	/* Append extent for new block (includes tree splitting if needed) */
-	rc = ext4_extent_append_extent(inode_ref, path, &path_ptr, new_block_idx);
+	rc = ext4_extent_append_extent(inode_ref, path, new_block_idx);
 	if (rc != EOK) {
 		ext4_balloc_free_block(inode_ref, phys_block);
 		goto finish;
 	}
+
+	uint32_t tree_depth = ext4_extent_header_get_depth(path->header);
+	path_ptr = path + tree_depth;
+
+	assert(tree_depth == path->depth);
 
 	/* Initialize newly created extent */
