Index: uspace/lib/ext4/libext4_directory.c
===================================================================
--- uspace/lib/ext4/libext4_directory.c	(revision 6f731f0ad7bad64469bf21da1cb873a3e14ead3f)
+++ uspace/lib/ext4/libext4_directory.c	(revision c30a0155d20e2d44c1d10feae9e7aa8c2a2b1b91)
@@ -314,11 +314,9 @@
 
 int ext4_directory_add_entry(ext4_filesystem_t *fs, ext4_inode_ref_t * parent,
-		const char *entry_name, ext4_inode_ref_t *child)
+		const char *name, ext4_inode_ref_t *child)
 {
 	int rc;
 
-	EXT4FS_DBG("adding entry to directory \%u [ino = \%u, name = \%s]", parent->index, child->index, entry_name);
-
-	uint16_t name_len = strlen(entry_name);
+	EXT4FS_DBG("adding entry to directory \%u [ino = \%u, name = \%s]", parent->index, child->index, name);
 
 	// Index adding (if allowed)
@@ -326,5 +324,5 @@
 			ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX)) {
 
-		rc = ext4_directory_dx_add_entry(fs, parent, child, name_len, entry_name);
+		rc = ext4_directory_dx_add_entry(fs, parent, child, name);
 
 		// Check if index is not corrupted
@@ -347,71 +345,45 @@
 	// Linear algorithm
 
-	ext4_directory_iterator_t it;
-	rc = ext4_directory_iterator_init(&it, fs, parent, 0);
-	if (rc != EOK) {
-		return rc;
-	}
-
+	EXT4FS_DBG("Linear algorithm");
+
+	uint32_t iblock, fblock;
 	uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
-	uint16_t required_len = 8 + name_len + (4 - name_len % 4);
-
-	while (it.current != NULL) {
-		uint32_t entry_inode = ext4_directory_entry_ll_get_inode(it.current);
-		uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(it.current);
-
-		if ((entry_inode == 0) && (rec_len >= required_len)) {
-
-			ext4_directory_write_entry(fs->superblock, it.current, rec_len,
-					child, entry_name, name_len);
-			it.current_block->dirty = true;
-			return ext4_directory_iterator_fini(&it);
-		}
-
-		if (entry_inode != 0) {
-			uint16_t used_name_len = ext4_directory_entry_ll_get_name_length(
-					fs->superblock, it.current);
-
-			uint16_t used_space = 8 + used_name_len;
-			if ((used_name_len % 4) != 0) {
-				used_space += 4 - (used_name_len % 4);
-			}
-			uint16_t free_space = rec_len - used_space;
-
-			EXT4FS_DBG("rec_len = \%u, used_space = \%u, free space = \%u", rec_len, used_space, free_space);
-
-			if (free_space >= required_len) {
-
-				// Cut tail of current entry
-				ext4_directory_entry_ll_set_entry_length(it.current, used_space);
-
-				// SEEK manually
-				uint32_t local_offset = (it.current_offset % block_size);
-				local_offset += used_space;
-				ext4_directory_entry_ll_t *new_entry = it.current_block->data + local_offset;
-
-				// We are sure, that both entries are in the same data block
-				// dirtyness will be set now
-
-				ext4_directory_write_entry(fs->superblock, new_entry,
-						free_space, child, entry_name, name_len);
-				it.current_block->dirty = true;
-				return ext4_directory_iterator_fini(&it);
-			}
-
-		}
-
-		rc = ext4_directory_iterator_next(&it);
-		if (rc != EOK) {
-			return rc;
-		}
-	}
-
-	// Destroy iterator
-	ext4_directory_iterator_fini(&it);
+	uint32_t inode_size = ext4_inode_get_size(fs->superblock, parent->inode);
+	uint32_t total_blocks = inode_size / block_size;
+
+	uint32_t name_len = strlen(name);
+
+	bool success = false;
+	for (iblock = 0; iblock < total_blocks; ++iblock) {
+
+		rc = ext4_filesystem_get_inode_data_block_index(fs, parent->inode, iblock, &fblock);
+		if (rc != EOK) {
+			return rc;
+		}
+
+		block_t *block;
+		rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			return rc;
+		}
+
+		rc = ext4_directory_try_insert_entry(fs->superblock, block, child, name, name_len);
+		if (rc == EOK) {
+			success = true;
+		}
+
+		rc = block_put(block);
+		if (rc != EOK) {
+			return rc;
+		}
+
+		if (success) {
+			return EOK;
+		}
+	}
+
 
 	EXT4FS_DBG("NO FREE SPACE - needed to allocate block");
 
-	uint32_t fblock;
-	uint32_t iblock;
 	rc = ext4_directory_append_block(fs, parent, &fblock, &iblock);
 	if (rc != EOK) {
@@ -428,9 +400,6 @@
 	// Fill block with zeroes
 	memset(new_block->data, 0, block_size);
-
 	ext4_directory_entry_ll_t *block_entry = new_block->data;
-
-	ext4_directory_write_entry(fs->superblock, block_entry, block_size, 
-	child, entry_name, name_len);
+	ext4_directory_write_entry(fs->superblock, block_entry, block_size, child, name, name_len);
 
 	new_block->dirty = true;
@@ -556,4 +525,59 @@
 }
 
+int ext4_directory_try_insert_entry(ext4_superblock_t *sb,
+		block_t *target_block, ext4_inode_ref_t *child,
+		const char *name, uint32_t name_len)
+{
+   	uint32_t block_size = ext4_superblock_get_block_size(sb);
+   	uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len;
+   	if ((required_len % 4) != 0) {
+   		required_len += 4 - (required_len % 4);
+   	}
+
+   	ext4_directory_entry_ll_t *dentry = target_block->data;
+   	ext4_directory_entry_ll_t *stop = target_block->data + block_size;
+
+   	while (dentry < stop) {
+
+   		uint32_t inode = ext4_directory_entry_ll_get_inode(dentry);
+   		uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry);
+
+   		if ((inode == 0) && (rec_len >= required_len)) {
+   			ext4_directory_write_entry(sb, dentry, rec_len, child, name, name_len);
+   			target_block->dirty = true;
+   			return EOK;
+   		}
+
+   		if (inode != 0) {
+   			uint16_t used_name_len =
+   					ext4_directory_entry_ll_get_name_length(sb, dentry);
+
+   			uint16_t used_space =
+   					sizeof(ext4_fake_directory_entry_t) + used_name_len;
+   			if ((used_name_len % 4) != 0) {
+   				used_space += 4 - (used_name_len % 4);
+   			}
+   			uint16_t free_space = rec_len - used_space;
+
+   			if (free_space >= required_len) {
+
+   				// Cut tail of current entry
+   				ext4_directory_entry_ll_set_entry_length(dentry, used_space);
+   				ext4_directory_entry_ll_t *new_entry =
+   						(void *)dentry + used_space;
+   				ext4_directory_write_entry(sb, new_entry,
+   						free_space, child, name, name_len);
+
+   				target_block->dirty = true;
+				return EOK;
+   			}
+   		}
+
+   		dentry = (void *)dentry + rec_len;
+   	}
+
+   	return ENOSPC;
+}
+
 
 /**
Index: uspace/lib/ext4/libext4_directory.h
===================================================================
--- uspace/lib/ext4/libext4_directory.h	(revision 6f731f0ad7bad64469bf21da1cb873a3e14ead3f)
+++ uspace/lib/ext4/libext4_directory.h	(revision c30a0155d20e2d44c1d10feae9e7aa8c2a2b1b91)
@@ -106,4 +106,6 @@
 		ext4_inode_ref_t *, const char *);
 
+extern int ext4_directory_try_insert_entry(ext4_superblock_t *,
+		block_t *, ext4_inode_ref_t *, const char *, uint32_t);
 #endif
 
Index: uspace/lib/ext4/libext4_directory_index.c
===================================================================
--- uspace/lib/ext4/libext4_directory_index.c	(revision 6f731f0ad7bad64469bf21da1cb873a3e14ead3f)
+++ uspace/lib/ext4/libext4_directory_index.c	(revision c30a0155d20e2d44c1d10feae9e7aa8c2a2b1b91)
@@ -503,5 +503,5 @@
 		block_t *old_data_block, ext4_directory_dx_block_t *index_block, block_t **new_data_block)
 {
-	int rc;
+	int rc = EOK;
 
 	uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
@@ -652,8 +652,8 @@
 
 int ext4_directory_dx_add_entry(ext4_filesystem_t *fs,
-		ext4_inode_ref_t *parent, ext4_inode_ref_t *child,
-		size_t name_size, const char *name)
-{
-	int rc;
+		ext4_inode_ref_t *parent, ext4_inode_ref_t *child, const char *name)
+{
+	int rc = EOK;
+	int rc2;
 
 	// get direct block 0 (index root)
@@ -670,6 +670,7 @@
 	}
 
+	uint32_t name_len = strlen(name);
 	ext4_hash_info_t hinfo;
-	rc = ext4_directory_hinfo_init(&hinfo, root_block, fs->superblock, name_size, name);
+	rc = ext4_directory_hinfo_init(&hinfo, root_block, fs->superblock, name_len, name);
 	if (rc != EOK) {
 		block_put(root_block);
@@ -702,62 +703,13 @@
    	}
 
-   	uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
-   	uint16_t required_len = 8 + name_size + (4 - name_size % 4);
-
-   	ext4_directory_entry_ll_t *de = target_block->data;
-   	ext4_directory_entry_ll_t *stop = target_block->data + block_size;
-
-   	while (de < stop) {
-
-   		uint32_t de_inode = ext4_directory_entry_ll_get_inode(de);
-   		uint16_t de_rec_len = ext4_directory_entry_ll_get_entry_length(de);
-
-   		if ((de_inode == 0) && (de_rec_len >= required_len)) {
-   			ext4_directory_write_entry(fs->superblock, de, de_rec_len,
-   				child, name, name_size);
-
-   				// TODO cleanup
-   				target_block->dirty = true;
-   				rc = block_put(target_block);
-   				if (rc != EOK) {
-   					return EXT4_ERR_BAD_DX_DIR;
-   				}
-   				return EOK;
-   		}
-
-   		if (de_inode != 0) {
-   			uint16_t used_name_len = ext4_directory_entry_ll_get_name_length(
-   					fs->superblock, de);
-
-   			uint16_t used_space = 8 + used_name_len;
-   			if ((used_name_len % 4) != 0) {
-   				used_space += 4 - (used_name_len % 4);
-   			}
-   			uint16_t free_space = de_rec_len - used_space;
-
-   			if (free_space >= required_len) {
-
-   				// Cut tail of current entry
-   				ext4_directory_entry_ll_set_entry_length(de, used_space);
-   				ext4_directory_entry_ll_t *new_entry = (void *)de + used_space;
-   				ext4_directory_write_entry(fs->superblock, new_entry,
-   					free_space, child, name, name_size);
-
-   				// TODO cleanup
-   				target_block->dirty = true;
-   				rc = block_put(target_block);
-				if (rc != EOK) {
-					return EXT4_ERR_BAD_DX_DIR;
-				}
-				return EOK;
-
-   			}
-
-   		}
-
-   		de = (void *)de + de_rec_len;
+   	rc = ext4_directory_try_insert_entry(fs->superblock, target_block, child, name, name_len);
+   	if (rc == EOK) {
+   		goto cleanup;
+
    	}
 
     EXT4FS_DBG("no free space found");
+
+    uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
 
 	ext4_directory_dx_entry_t *entries = ((ext4_directory_dx_node_t *) dx_block->block->data)->entries;
@@ -786,5 +738,5 @@
 		rc =  ext4_directory_append_block(fs, parent, &new_fblock, &new_iblock);
 		if (rc != EOK) {
-			// TODO error
+			goto cleanup;
 		}
 
@@ -793,5 +745,5 @@
 		rc = block_get(&new_block, fs->device, new_fblock, BLOCK_FLAGS_NOREAD);
 		if (rc != EOK) {
-			// TODO error
+			goto cleanup;
 		}
 
@@ -873,60 +825,31 @@
 	}
 
-	// TODO Where to save new entry
+	// Where to save new entry
 	uint32_t new_block_hash = ext4_directory_dx_entry_get_hash(dx_block->position + 1);
 	if (hinfo.hash >= new_block_hash) {
-		de = new_block->data;
-		stop = new_block->data + block_size;
+		rc = ext4_directory_try_insert_entry(fs->superblock, new_block, child, name, name_len);
 	} else {
-		de = target_block->data;
-		stop = target_block->data + block_size;
-	}
-
-   	while (de < stop) {
-
-   		uint32_t de_inode = ext4_directory_entry_ll_get_inode(de);
-   		uint16_t de_rec_len = ext4_directory_entry_ll_get_entry_length(de);
-
-   		if ((de_inode == 0) && (de_rec_len >= required_len)) {
-   			ext4_directory_write_entry(fs->superblock, de, de_rec_len,
-   				child, name, name_size);
-   				goto success;
-   		}
-
-   		if (de_inode != 0) {
-   			uint16_t used_name_len = ext4_directory_entry_ll_get_name_length(
-   					fs->superblock, de);
-
-   			uint16_t used_space = 8 + used_name_len;
-   			if ((used_name_len % 4) != 0) {
-   				used_space += 4 - (used_name_len % 4);
-   			}
-   			uint16_t free_space = de_rec_len - used_space;
-
-   			if (free_space >= required_len) {
-
-   				// Cut tail of current entry
-   				ext4_directory_entry_ll_set_entry_length(de, used_space);
-   				ext4_directory_entry_ll_t *new_entry = (void *)de + used_space;
-   				ext4_directory_write_entry(fs->superblock, new_entry,
-   					free_space, child, name, name_size);
-
-   				goto success;
-   			}
-
-   		}
-
-   		de = (void *)de + de_rec_len;
-   	}
-
-success:
+		rc = ext4_directory_try_insert_entry(fs->superblock, target_block, child, name, name_len);
+	}
+
+	if (rc != EOK) {
+		goto terminate;
+	}
+
+
+terminate:
+	rc = block_put(new_block);
+	if (rc != EOK) {
+		EXT4FS_DBG("error writing new block");
+	}
+
+
+cleanup:
+
+	rc2 = rc;
 
 	rc = block_put(target_block);
 	if (rc != EOK) {
-		EXT4FS_DBG("error writing target block");
-	}
-	rc = block_put(new_block);
-	if (rc != EOK) {
-		EXT4FS_DBG("error writing new block");
+		return rc;
 	}
 
@@ -936,10 +859,10 @@
 		rc = block_put(dx_it->block);
 		if (rc != EOK) {
-			EXT4FS_DBG("error writing index block \%u", (uint32_t)dx_it->block->pba);
+			return rc;
 		}
 		dx_it++;
 	}
 
-	return EOK;
+	return rc2;
 }
 
Index: uspace/lib/ext4/libext4_directory_index.h
===================================================================
--- uspace/lib/ext4/libext4_directory_index.h	(revision 6f731f0ad7bad64469bf21da1cb873a3e14ead3f)
+++ uspace/lib/ext4/libext4_directory_index.h	(revision c30a0155d20e2d44c1d10feae9e7aa8c2a2b1b91)
@@ -126,5 +126,5 @@
 		ext4_filesystem_t *, ext4_inode_ref_t *, size_t, const char *);
 extern int ext4_directory_dx_add_entry(ext4_filesystem_t *,
-		ext4_inode_ref_t *, ext4_inode_ref_t *, size_t, const char *);
+		ext4_inode_ref_t *, ext4_inode_ref_t *, const char *);
 
 #endif
