Index: uspace/lib/ext4/libext4_extent.c
===================================================================
--- uspace/lib/ext4/libext4_extent.c	(revision a2fa3501b28d432eea4b5c7ec90dd02325ef3d0d)
+++ uspace/lib/ext4/libext4_extent.c	(revision 0d4db0f4252afb0a982d0f61fe3cfa55af93dc71)
@@ -205,5 +205,5 @@
 	r = l + entries_count - 1;
 
-	while (l <= r) {
+	while (l < r) {
 		m = l + (r - l) / 2;
 		uint32_t first_block = ext4_extent_get_first_block(m);
@@ -246,7 +246,8 @@
 
 
-	ext4_extent_t* extent;
+	ext4_extent_t* extent = NULL;
 	ext4_extent_binsearch(header, &extent, iblock);
 
+	assert(extent != NULL);
 
 	uint32_t phys_block;
@@ -264,101 +265,133 @@
 }
 
-//static int ext4_extent_find_extent(ext4_filesystem_t *fs,
-//		ext4_inode_ref_t *inode_ref, uint32_t iblock, ext4_extent_path_t **ret_path)
-//{
-//	int rc;
-//
-//	ext4_extent_header_t *eh =
-//			ext4_inode_get_extent_header(inode_ref->inode);
-//
-//	uint16_t depth = ext4_extent_header_get_depth(eh);
-//
-//	ext4_extent_path_t *tmp_path;
-//
-//	// Added 2 for possible tree growing
-//	tmp_path = malloc(sizeof(ext4_extent_path_t) * (depth + 2));
-//	if (tmp_path == NULL) {
-//		return ENOMEM;
-//	}
-//
-//	tmp_path[0].block = inode_ref->block;
-//	tmp_path[0].header = eh;
-//
-//	uint16_t pos = 0;
-//	while (ext4_extent_header_get_depth(eh) != 0) {
-//
-//		ext4_extent_binsearch_idx(tmp_path[pos].header, &tmp_path[pos].index, iblock);
-//
-//		tmp_path[pos].depth = depth;
-//		tmp_path[pos].extent = NULL;
-//
-//		assert(tmp_path[pos].index != NULL);
-//
-//		uint64_t fblock = ext4_extent_index_get_leaf(tmp_path[pos].index);
-//
-//		block_t *block;
-//		rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
-//		if (rc != EOK) {
-//			// TODO cleanup
-//			EXT4FS_DBG("ERRRR");
-//			return rc;
-//		}
-//
-//		pos++;
-//
-//		eh = (ext4_extent_header_t *)block->data;
-//		tmp_path[pos].block = block;
-//		tmp_path[pos].header = eh;
-//
-//	}
-//
-//	tmp_path[pos].depth = 0;
-//	tmp_path[pos].extent = NULL;
-//	tmp_path[pos].index = NULL;
-//
-//    /* find extent */
-//	ext4_extent_binsearch(tmp_path[pos].header, &tmp_path[pos].extent, iblock);
-//
-//	*ret_path = tmp_path;
-//
-//	return EOK;
-//}
-
-
-//int ext4_extent_find_block(ext4_filesystem_t *fs,
-//		ext4_inode_ref_t *inode_ref, uint32_t iblock, uint32_t *fblock)
-//{
-//	int rc;
-//
-//	ext4_extent_path_t *path;
-//	rc = ext4_extent_find_extent(fs, inode_ref, iblock, &path);
-//	if (rc != EOK) {
-//		return rc;
-//	}
-//
-//	uint16_t depth = path->depth;
-//
-//	ext4_extent_t *extent = path[depth].extent;
-//
-//	uint32_t phys_block;
-//	phys_block = ext4_extent_get_start(extent) + iblock;
-//	phys_block -= ext4_extent_get_first_block(extent);
-//
-//	*fblock = phys_block;
-//
-//	// Put loaded blocks
-//	// From 1 -> 0 is a block with inode data
-//	for (uint16_t i = 1; i < depth; ++i) {
-//		if (path[i].block) {
-//			block_put(path[i].block);
-//		}
-//	}
-//
-//	// Destroy temporary data structure
-//	free(path);
-//
-//	return EOK;
-//
-//}
+static int ext4_extent_find_extent(ext4_inode_ref_t *inode_ref,
+		uint32_t iblock, ext4_extent_path_t **ret_path)
+{
+	int rc;
+
+	ext4_extent_header_t *eh =
+			ext4_inode_get_extent_header(inode_ref->inode);
+
+	uint16_t depth = ext4_extent_header_get_depth(eh);
+
+//	EXT4FS_DBG("depth = \%u", depth);
+//	EXT4FS_DBG("header = \%u", (uint32_t)eh);
+//	EXT4FS_DBG("entries_count = \%u", ext4_extent_header_get_entries_count(eh));
+//	EXT4FS_DBG("max entries_count = \%u", ext4_extent_header_get_max_entries_count(eh));
+
+	ext4_extent_path_t *tmp_path;
+
+	// Added 2 for possible tree growing
+	tmp_path = malloc(sizeof(ext4_extent_path_t) * (depth + 2));
+	if (tmp_path == NULL) {
+		return ENOMEM;
+	}
+
+	tmp_path[0].block = inode_ref->block;
+	tmp_path[0].header = eh;
+
+	uint16_t pos = 0;
+	while (ext4_extent_header_get_depth(eh) != 0) {
+
+		ext4_extent_binsearch_idx(tmp_path[pos].header, &tmp_path[pos].index, iblock);
+
+		tmp_path[pos].depth = depth;
+		tmp_path[pos].extent = NULL;
+
+		assert(tmp_path[pos].index != NULL);
+
+		uint64_t fblock = ext4_extent_index_get_leaf(tmp_path[pos].index);
+
+		block_t *block;
+		rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			// TODO cleanup
+			EXT4FS_DBG("ERRRR");
+			return rc;
+		}
+
+		pos++;
+
+		eh = (ext4_extent_header_t *)block->data;
+		tmp_path[pos].block = block;
+		tmp_path[pos].header = eh;
+
+	}
+
+	tmp_path[pos].depth = 0;
+	tmp_path[pos].extent = NULL;
+	tmp_path[pos].index = NULL;
+
+    /* find extent */
+	ext4_extent_binsearch(tmp_path[pos].header, &tmp_path[pos].extent, iblock);
+
+	EXT4FS_DBG("extent = \%u", (uint32_t)tmp_path[pos].extent);
+
+	*ret_path = tmp_path;
+
+	return EOK;
+}
+
+int ext4_extent_release_block(ext4_inode_ref_t *inode_ref, uint32_t iblock)
+{
+	int rc;
+
+	ext4_extent_path_t *path;
+	rc = ext4_extent_find_extent(inode_ref, iblock, &path);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	ext4_extent_path_t *path_ptr = path;
+	while (path_ptr->depth != 0) {
+		EXT4FS_DBG("depth = \%u", path_ptr->depth);
+		path_ptr++;
+	}
+
+	assert(path_ptr->extent != NULL);
+
+	uint32_t fblock;
+	fblock = ext4_extent_get_start(path_ptr->extent) + iblock;
+	fblock -= ext4_extent_get_first_block(path_ptr->extent);
+
+	uint16_t block_count = ext4_extent_get_block_count(path_ptr->extent);
+
+	assert((ext4_extent_get_first_block(path_ptr->extent) + block_count - 1) == iblock);
+
+	block_count--;
+	ext4_extent_set_block_count(path_ptr->extent, block_count);
+
+	if (block_count == 0) {
+		uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header);
+		entries--;
+		ext4_extent_header_set_entries_count(path_ptr->header, entries);
+
+		// TODO if empty leaf, release it
+
+	}
+
+	path_ptr->block->dirty = true;
+
+	rc = ext4_balloc_free_block(inode_ref, fblock);
+	if (rc != EOK) {
+		// TODO handle error
+	}
+
+	uint16_t depth = path->depth;
+
+	// Put loaded blocks
+	// From 1 -> 0 is a block with inode data
+	for (uint16_t i = 1; i < depth; ++i) {
+		if (path[i].block) {
+			block_put(path[i].block);
+		}
+	}
+
+	// Destroy temporary data structure
+	free(path);
+
+
+	return EOK;
+}
 
 /**
Index: uspace/lib/ext4/libext4_extent.h
===================================================================
--- uspace/lib/ext4/libext4_extent.h	(revision a2fa3501b28d432eea4b5c7ec90dd02325ef3d0d)
+++ uspace/lib/ext4/libext4_extent.h	(revision 0d4db0f4252afb0a982d0f61fe3cfa55af93dc71)
@@ -62,4 +62,6 @@
 
 extern int ext4_extent_find_block(ext4_inode_ref_t *, uint32_t, uint32_t *);
+extern int ext4_extent_release_block(ext4_inode_ref_t *, uint32_t);
+
 #endif
 
Index: uspace/lib/ext4/libext4_filesystem.c
===================================================================
--- uspace/lib/ext4/libext4_filesystem.c	(revision a2fa3501b28d432eea4b5c7ec90dd02325ef3d0d)
+++ uspace/lib/ext4/libext4_filesystem.c	(revision 0d4db0f4252afb0a982d0f61fe3cfa55af93dc71)
@@ -783,30 +783,9 @@
 	ext4_filesystem_t *fs = inode_ref->fs;
 
-	/* TODO Handle extents */
-//	if (ext4_superblock_has_feature_incompatible(fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS) &&
-//			ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)) {
-////		rc = ext4_extent_find_block(fs, inode_ref, iblock, &current_block);
-////
-////		if (rc != EOK) {
-////			return rc;
-////		}
-////
-////		*fblock = current_block;
-//
-//		// TODO release block from extents (and return fblock)
-//
-//		fblock = 0;
-//
-//		if (fblock == 0) {
-//			return EOK;
-//		}
-//
-//		return ext4_balloc_free_block(fs, inode_ref, fblock);
-//
-//		return EOK;
-//
-//	}
-
-
+	if (ext4_superblock_has_feature_incompatible(fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS) &&
+			ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)) {
+
+		return ext4_extent_release_block(inode_ref, iblock);
+	}
 
 	ext4_inode_t *inode = inode_ref->inode;
