Index: uspace/srv/fs/ext2fs/ext2fs_ops.c
===================================================================
--- uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision df386574003210ff36963b08b86f46840fe22ad9)
+++ uspace/srv/fs/ext2fs/ext2fs_ops.c	(revision 529edc66ca1afec4d3001dccda72d65b2e207159)
@@ -74,4 +74,6 @@
 static void ext2fs_read_directory(ipc_callid_t, ipc_callid_t, aoff64_t,
 	size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
+static void ext2fs_read_file(ipc_callid_t, ipc_callid_t, aoff64_t,
+	size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
 
 /*
@@ -596,6 +598,5 @@
 	if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
 		    EXT2_INODE_MODE_FILE)) {
-		async_answer_0(callid, ENOTSUP);
-		async_answer_0(rid, ENOTSUP);
+		ext2fs_read_file(rid, callid, pos, size, inst, inode_ref);
 	}
 	else if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
@@ -700,4 +701,58 @@
 }
 
+void ext2fs_read_file(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
+	size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
+{
+	int rc;
+	uint32_t block_size;
+	aoff64_t file_block;
+	uint64_t file_size;
+	uint32_t fs_block;
+	size_t offset_in_block;
+	size_t bytes;
+	block_t *block;
+	
+	file_size = ext2_inode_get_size(inst->filesystem->superblock,
+		inode_ref->inode);
+	
+	if (pos >= file_size) {
+		// TODO: is this OK? return EIO?
+		async_data_read_finalize(callid, NULL, 0);
+		async_answer_1(rid, EOK, 0);
+		return;
+	}
+	
+	// For now, we only read data from one block at a time
+	block_size = ext2_superblock_get_block_size(inst->filesystem->superblock);
+	file_block = pos / block_size;
+	offset_in_block = pos % block_size;
+	bytes = min(block_size - offset_in_block, size);
+	
+	rc = ext2_filesystem_get_inode_data_block_index(inst->filesystem,
+		inode_ref->inode, file_block, &fs_block);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(rid, rc);
+		return;
+	}
+	
+	rc = block_get(&block, inst->devmap_handle, fs_block, BLOCK_FLAGS_NONE);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_answer_0(rid, rc);
+		return;
+	}
+	
+	async_data_read_finalize(callid, block->data, bytes);
+	
+	rc = block_put(block);
+	if (rc != EOK) {
+		async_answer_0(rid, rc);
+		return;
+	}
+		
+	async_answer_1(rid, EOK, bytes);
+}
+
 void ext2fs_write(ipc_callid_t rid, ipc_call_t *request)
 {
