Index: uspace/lib/ext4/libext4.h
===================================================================
--- uspace/lib/ext4/libext4.h	(revision bf66ef4449472db94d23f414adce9ea2a7577ff4)
+++ uspace/lib/ext4/libext4.h	(revision 82d78166a9fc4686450faba350a4b64efd19e98b)
@@ -42,4 +42,5 @@
 #include "libext4_filesystem.h"
 #include "libext4_hash.h"
+#include "libext4_ialloc.h"
 #include "libext4_inode.h"
 #include "libext4_superblock.h"
Index: uspace/lib/ext4/libext4_filesystem.c
===================================================================
--- uspace/lib/ext4/libext4_filesystem.c	(revision bf66ef4449472db94d23f414adce9ea2a7577ff4)
+++ uspace/lib/ext4/libext4_filesystem.c	(revision 82d78166a9fc4686450faba350a4b64efd19e98b)
@@ -283,4 +283,174 @@
 }
 
+int ext4_filesystem_free_inode(ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref)
+{
+	int rc;
+	// release all indirect blocks
+
+	uint32_t fblock;
+
+	// 1) Single indirect
+	fblock = ext4_inode_get_indirect_block(inode_ref->inode, 0);
+	if (fblock != 0) {
+		rc = ext4_balloc_free_block(fs, inode_ref, fblock);
+		if (rc != EOK) {
+			// TODO error
+		}
+
+		ext4_inode_set_indirect_block(inode_ref->inode, 0, 0);
+	}
+
+	block_t *block;
+	uint32_t block_size = ext4_superblock_get_block_size(fs->superblock);
+	uint32_t count = block_size / sizeof(uint32_t);
+
+	// 2) Double indirect
+	fblock = ext4_inode_get_indirect_block(inode_ref->inode, 1);
+	if (fblock != 0) {
+		rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			// TODO error
+		}
+
+		uint32_t ind_block;
+		for (uint32_t offset = 0; offset < count; ++offset) {
+			ind_block = uint32_t_le2host(((uint32_t*)block->data)[offset]);
+
+			if (ind_block != 0) {
+				rc = ext4_balloc_free_block(fs, inode_ref, ind_block);
+				if (rc != EOK) {
+					// TODO error
+				}
+			}
+		}
+
+		block_put(block);
+		rc = ext4_balloc_free_block(fs, inode_ref, fblock);
+		if (rc != EOK) {
+			// TODO error
+		}
+
+		ext4_inode_set_indirect_block(inode_ref->inode, 1, 0);
+	}
+
+
+	// 3) Tripple indirect
+	block_t *subblock;
+	fblock = ext4_inode_get_indirect_block(inode_ref->inode, 2);
+	if (fblock != 0) {
+		rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			// TODO error
+		}
+
+		uint32_t ind_block;
+		for (uint32_t offset = 0; offset < count; ++offset) {
+			ind_block = uint32_t_le2host(((uint32_t*)block->data)[offset]);
+
+			if (ind_block != 0) {
+				rc = block_get(&subblock, fs->device, ind_block, BLOCK_FLAGS_NONE);
+				if (rc != EOK) {
+					// TODO error
+				}
+
+				uint32_t ind_subblock;
+				for (uint32_t suboffset = 0; suboffset < count; ++suboffset) {
+					ind_subblock = uint32_t_le2host(((uint32_t*)subblock->data)[suboffset]);
+
+					if (ind_subblock != 0) {
+						rc = ext4_balloc_free_block(fs, inode_ref, ind_subblock);
+						if (rc != EOK) {
+							// TODO error
+						}
+					}
+
+				}
+				block_put(subblock);
+
+			}
+
+			rc = ext4_balloc_free_block(fs, inode_ref, ind_block);
+			if (rc != EOK) {
+				// TODO error
+			}
+
+
+		}
+
+		block_put(block);
+		rc = ext4_balloc_free_block(fs, inode_ref, fblock);
+		if (rc != EOK) {
+			// TODO error
+		}
+
+		ext4_inode_set_indirect_block(inode_ref->inode, 2, 0);
+	}
+
+	// Free inode
+	rc = ext4_ialloc_free_inode(fs, inode_ref);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	return EOK;
+}
+
+int ext4_filesystem_truncate_inode(ext4_filesystem_t *fs,
+		ext4_inode_ref_t *inode_ref, aoff64_t new_size)
+{
+	aoff64_t old_size;
+	aoff64_t size_diff;
+
+	if (! ext4_inode_can_truncate(fs->superblock, inode_ref->inode)) {
+		// Unable to truncate
+		return EINVAL;
+	}
+
+	old_size = ext4_inode_get_size(fs->superblock, inode_ref->inode);
+
+	if (old_size == new_size) {
+		// Nothing to do
+		return EOK;
+	}
+
+	uint32_t block_size;
+	uint32_t blocks_count, total_blocks;
+	uint32_t i;
+
+	block_size  = ext4_superblock_get_block_size(fs->superblock);
+
+	if (old_size < new_size) {
+		// Currently not supported to expand the file
+		// TODO
+		EXT4FS_DBG("trying to expand the file");
+		return EINVAL;
+	}
+
+	size_diff = old_size - new_size;
+	blocks_count = size_diff / block_size;
+	if (size_diff % block_size != 0) {
+		blocks_count++;
+	}
+
+	total_blocks = old_size / block_size;
+	if (old_size % block_size != 0) {
+		total_blocks++;
+	}
+
+	// starting from 1 because of logical blocks are numbered from 0
+	for (i = 1; i <= blocks_count; ++i) {
+		// TODO check retval
+		// TODO decrement inode->blocks_count
+
+		ext4_filesystem_release_inode_block(fs, inode_ref, total_blocks - i);
+	}
+
+	ext4_inode_set_size(inode_ref->inode, new_size);
+
+	inode_ref->dirty = true;
+
+	return EOK;
+}
+
 int ext4_filesystem_get_inode_data_block_index(ext4_filesystem_t *fs, ext4_inode_t* inode,
     aoff64_t iblock, uint32_t* fblock)
Index: uspace/lib/ext4/libext4_filesystem.h
===================================================================
--- uspace/lib/ext4/libext4_filesystem.h	(revision bf66ef4449472db94d23f414adce9ea2a7577ff4)
+++ uspace/lib/ext4/libext4_filesystem.h	(revision 82d78166a9fc4686450faba350a4b64efd19e98b)
@@ -61,4 +61,7 @@
 		ext4_inode_ref_t **);
 extern int ext4_filesystem_put_inode_ref(ext4_inode_ref_t *);
+extern int ext4_filesystem_free_inode(ext4_filesystem_t *, ext4_inode_ref_t *);
+extern int ext4_filesystem_truncate_inode(ext4_filesystem_t *,
+		ext4_inode_ref_t *, aoff64_t);
 extern int ext4_filesystem_get_inode_data_block_index(ext4_filesystem_t *,
 	ext4_inode_t *, aoff64_t iblock, uint32_t *);
Index: uspace/lib/ext4/libext4_ialloc.c
===================================================================
--- uspace/lib/ext4/libext4_ialloc.c	(revision bf66ef4449472db94d23f414adce9ea2a7577ff4)
+++ uspace/lib/ext4/libext4_ialloc.c	(revision 82d78166a9fc4686450faba350a4b64efd19e98b)
@@ -36,5 +36,80 @@
  */
 
+#include <errno.h>
 #include "libext4.h"
+
+static uint32_t ext4_ialloc_inode2index_in_group(ext4_superblock_t *sb,
+		uint32_t inode)
+{
+	uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
+	return (inode - 1) % inodes_per_group;
+}
+
+static uint32_t ext4_ialloc_get_bgid_of_inode(ext4_superblock_t *sb,
+		uint32_t inode)
+{
+	uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
+	return (inode - 1) / inodes_per_group;
+
+}
+
+
+int ext4_ialloc_free_inode(ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref)
+{
+	int rc;
+	uint32_t block_group = ext4_ialloc_get_bgid_of_inode(
+			fs->superblock, inode_ref->index);
+	uint32_t index_in_group = ext4_ialloc_inode2index_in_group(
+			fs->superblock, inode_ref->index);
+
+	ext4_block_group_ref_t *bg_ref;
+	rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
+	if (rc != EOK) {
+		EXT4FS_DBG("error in loading bg_ref \%d", rc);
+		return rc;
+	}
+
+	uint32_t bitmap_block_addr = ext4_block_group_get_inode_bitmap(
+			bg_ref->block_group, fs->superblock);
+	block_t *bitmap_block;
+	rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
+	if (rc != EOK) {
+		EXT4FS_DBG("error in loading bitmap \%d", rc);
+		return rc;
+	}
+
+	ext4_bitmap_free_bit(bitmap_block->data, index_in_group);
+	bitmap_block->dirty = true;
+
+	rc = block_put(bitmap_block);
+	if (rc != EOK) {
+		// Error in saving bitmap
+		ext4_filesystem_put_block_group_ref(bg_ref);
+		EXT4FS_DBG("error in saving bitmap \%d", rc);
+		return rc;
+	}
+
+	// Update superblock free inodes count
+	uint32_t sb_free_inodes = ext4_superblock_get_free_inodes_count(fs->superblock);
+	sb_free_inodes--;
+	ext4_superblock_set_free_inodes_count(fs->superblock, sb_free_inodes);
+
+	// Update block group free inodes count
+	uint32_t free_inodes = ext4_block_group_get_free_inodes_count(
+			bg_ref->block_group, fs->superblock);
+	free_inodes++;
+	ext4_block_group_set_free_inodes_count(bg_ref->block_group,
+			fs->superblock, free_inodes);
+	bg_ref->dirty = true;
+
+	rc = ext4_filesystem_put_block_group_ref(bg_ref);
+	if (rc != EOK) {
+		EXT4FS_DBG("error in saving bg_ref \%d", rc);
+		// TODO error
+		return rc;
+	}
+
+	return EOK;
+}
 
 
Index: uspace/lib/ext4/libext4_ialloc.h
===================================================================
--- uspace/lib/ext4/libext4_ialloc.h	(revision bf66ef4449472db94d23f414adce9ea2a7577ff4)
+++ uspace/lib/ext4/libext4_ialloc.h	(revision 82d78166a9fc4686450faba350a4b64efd19e98b)
@@ -34,4 +34,8 @@
 #define LIBEXT4_LIBEXT4_IALLOC_H_
 
+#include "libext4_filesystem.h"
+#include "libext4_inode.h"
+
+extern int ext4_ialloc_free_inode(ext4_filesystem_t *, ext4_inode_ref_t *);
 
 #endif
