Index: uspace/srv/fs/minixfs/mfs.c
===================================================================
--- uspace/srv/fs/minixfs/mfs.c	(revision 287454704569553cb58e2dbbbe0569b93cecbf85)
+++ uspace/srv/fs/minixfs/mfs.c	(revision 8a49fed9a95067b90465e853600fc1a0f5dba7dd)
@@ -122,4 +122,7 @@
 			mfs_write(callid, &call);
 			break;
+		case VFS_OUT_TRUNCATE:
+			mfs_truncate(callid, &call);
+			break;
 		default:
 			async_answer_0(callid, ENOTSUP);
Index: uspace/srv/fs/minixfs/mfs.h
===================================================================
--- uspace/srv/fs/minixfs/mfs.h	(revision 287454704569553cb58e2dbbbe0569b93cecbf85)
+++ uspace/srv/fs/minixfs/mfs.h	(revision 8a49fed9a95067b90465e853600fc1a0f5dba7dd)
@@ -29,5 +29,5 @@
 /** @addtogroup fs
  * @{
- */ 
+ */
 
 #ifndef _MFS_H_
@@ -111,16 +111,16 @@
 /*Generic MinixFS inode*/
 struct mfs_ino_info {
-        uint16_t        i_mode;
-        uint16_t        i_nlinks;
-        int16_t         i_uid;
-        uint16_t        i_gid;
-        size_t		i_size;
-        int32_t         i_atime;
-        int32_t         i_mtime;
-        int32_t         i_ctime;
-        /*Block numbers for direct zones*/
-        uint32_t        i_dzone[V2_NR_DIRECT_ZONES];
-        /*Block numbers for indirect zones*/
-        uint32_t        i_izone[V2_NR_INDIRECT_ZONES];
+	uint16_t	i_mode;
+	uint16_t	i_nlinks;
+	int16_t		i_uid;
+	uint16_t	i_gid;
+	size_t		i_size;
+	int32_t		i_atime;
+	int32_t		i_mtime;
+	int32_t		i_ctime;
+	/*Block numbers for direct zones*/
+	uint32_t	i_dzone[V2_NR_DIRECT_ZONES];
+	/*Block numbers for indirect zones*/
+	uint32_t	i_izone[V2_NR_INDIRECT_ZONES];
 
 	/*The following fields do not exist on disk but only in memory*/
@@ -159,5 +159,5 @@
 extern void mfs_lookup(ipc_callid_t rid, ipc_call_t *request);
 extern int mfs_instance_get(devmap_handle_t handle,
-				struct mfs_instance **instance);
+			    struct mfs_instance **instance);
 
 extern void mfs_stat(ipc_callid_t rid, ipc_call_t *request);
@@ -171,15 +171,21 @@
 mfs_write(ipc_callid_t rid, ipc_call_t *request);
 
+extern void
+mfs_truncate(ipc_callid_t rid, ipc_call_t *request);
+
 /*mfs_inode.c*/
-int
+extern int
 get_inode(struct mfs_instance *inst, struct mfs_ino_info **ino_i,
-				fs_index_t index);
+	  fs_index_t index);
 
 extern int
 put_inode(struct mfs_node *mnode);
 
-int
+extern int
 inode_grow(struct mfs_node *mnode, size_t size_grow);
 
+extern int
+inode_shrink(struct mfs_node *mnode, size_t size_shrink);
+
 /*mfs_rw.c*/
 extern int
@@ -188,5 +194,5 @@
 extern int
 write_map(struct mfs_node *mnode, uint32_t pos, uint32_t new_zone,
-				uint32_t *old_zone);
+	  uint32_t *old_zone);
 
 extern int
@@ -196,10 +202,10 @@
 extern int
 read_directory_entry(struct mfs_node *mnode,
-			struct mfs_dentry_info **d_info, unsigned index);
+		     struct mfs_dentry_info **d_info, unsigned index);
 
 extern int
 write_dentry(struct mfs_dentry_info *d_info);
 
-int
+extern int
 insert_dentry(struct mfs_node *mnode, const char *d_name, fs_index_t d_inum);
 
@@ -215,4 +221,4 @@
 /**
  * @}
- */ 
-
+ */
+
Index: uspace/srv/fs/minixfs/mfs_balloc.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_balloc.c	(revision 287454704569553cb58e2dbbbe0569b93cecbf85)
+++ uspace/srv/fs/minixfs/mfs_balloc.c	(revision 8a49fed9a95067b90465e853600fc1a0f5dba7dd)
@@ -72,6 +72,5 @@
 
 	r = block_get(&b, inst->handle, block, BLOCK_FLAGS_NONE);
-	if (r != EOK)
-		goto out_err;
+	on_error(r, goto out_err);
 
 	/*Compute the bit index in the block*/
@@ -85,6 +84,5 @@
 	ptr[idx / chunk_bits] = conv32(sbi->native, chunk);
 	b->dirty = true;
-	r = EOK;
-	block_put(b);
+	r = block_put(b);
 
 out_err:
@@ -128,6 +126,5 @@
 				BLOCK_FLAGS_NONE);
 
-		if (r != EOK)
-			goto out;
+		on_error(r, goto out);
 
 		freebit = find_free_bit_and_set(b->data, sbi->block_size,
@@ -145,5 +142,6 @@
 		if (*idx > limit) {
 			/*Index is beyond the limit, it is invalid*/
-			block_put(b);
+			r = block_put(b);
+			on_error(r, goto out);
 			break;
 		}
@@ -151,6 +149,6 @@
 		*search = *idx;
 		b->dirty = true;
-		block_put(b);
-		goto found;
+		r = block_put(b);
+		goto out;
 	}
 
@@ -163,7 +161,4 @@
 	/*Free bit not found, return error*/
 	return ENOSPC;
-
-found:
-	r = EOK;
 
 out:
Index: uspace/srv/fs/minixfs/mfs_inode.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_inode.c	(revision 287454704569553cb58e2dbbbe0569b93cecbf85)
+++ uspace/srv/fs/minixfs/mfs_inode.c	(revision 8a49fed9a95067b90465e853600fc1a0f5dba7dd)
@@ -302,4 +302,54 @@
 
 int
+inode_shrink(struct mfs_node *mnode, size_t size_shrink)
+{
+	struct mfs_sb_info *sbi = mnode->instance->sbi;
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+	const size_t bs = sbi->block_size;
+	int r;
+
+	assert(size_shrink > 0);
+
+	const size_t old_size = ino_i->i_size;
+	const size_t new_size = ino_i->i_size - size_shrink;
+
+	assert(size_shrink <= old_size);
+
+	ino_i->dirty = true;
+
+	/*Compute the number of zones to free*/
+	unsigned zones_to_free = 0;
+	if (new_size == 0)
+		++zones_to_free;
+
+	zones_to_free += (old_size / bs) - (new_size / bs);
+
+	mfsdebug("zones to free = %u\n", zones_to_free);
+
+	uint32_t pos = old_size - 1;
+	unsigned i;
+	for (i = 0; i < zones_to_free; ++i, pos -= bs) {
+		uint32_t old_zone;
+
+		r = write_map(mnode, pos, 0, &old_zone);
+		on_error(r, goto exit_error);
+
+		ino_i->i_size -= bs;
+
+		if (old_zone == 0)
+			continue; /*Sparse block*/
+
+		r = mfs_free_bit(mnode->instance, old_zone, BMAP_ZONE);
+		on_error(r, goto exit_error);
+	}
+
+	ino_i->i_size = new_size;
+	return EOK;
+
+exit_error:
+	return r;
+}
+
+int
 inode_grow(struct mfs_node *mnode, size_t size_grow)
 {
Index: uspace/srv/fs/minixfs/mfs_ops.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_ops.c	(revision 287454704569553cb58e2dbbbe0569b93cecbf85)
+++ uspace/srv/fs/minixfs/mfs_ops.c	(revision 8a49fed9a95067b90465e853600fc1a0f5dba7dd)
@@ -791,4 +791,39 @@
 }
 
+void
+mfs_truncate(ipc_callid_t rid, ipc_call_t *request)
+{
+	devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(*request);
+	fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
+	aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request),
+						IPC_GET_ARG4(*request));
+	fs_node_t *fn;
+	int r;
+
+	mfsdebug("mfs_truncate()\n");
+
+	r = mfs_node_get(&fn, handle, index);
+	if (r != EOK) {
+		async_answer_0(rid, r);
+		return;
+	}
+
+	if (!fn) {
+		async_answer_0(rid, r);
+		return;
+	}
+
+	struct mfs_node *mnode = fn->data;
+	struct mfs_ino_info *ino_i = mnode->ino_i;
+
+	if (ino_i->i_size == size)
+		r = EOK;
+	else
+		r = inode_shrink(mnode, ino_i->i_size - size);
+
+	async_answer_0(rid, r);
+	mfs_node_put(fn);
+}
+
 int mfs_instance_get(devmap_handle_t handle, struct mfs_instance **instance)
 {
Index: uspace/srv/fs/minixfs/mfs_rw.c
===================================================================
--- uspace/srv/fs/minixfs/mfs_rw.c	(revision 287454704569553cb58e2dbbbe0569b93cecbf85)
+++ uspace/srv/fs/minixfs/mfs_rw.c	(revision 8a49fed9a95067b90465e853600fc1a0f5dba7dd)
@@ -83,8 +83,7 @@
 {
 	const struct mfs_sb_info *sbi = mnode->instance->sbi;
-	const int block_size = sbi->block_size;
 
 	/*Compute the relative block number in file*/
-	int rblock = pos / block_size;
+	int rblock = pos / sbi->block_size;
 
 	return rw_map_ondisk(old_zone, mnode, rblock, true, new_zone);
