Index: uspace/srv/fs/pipefs/pipefs.h
===================================================================
--- uspace/srv/fs/pipefs/pipefs.h	(revision 5bd4f2cdcf5b1214b80769737edcc5abdd052fc9)
+++ uspace/srv/fs/pipefs/pipefs.h	(revision 8d1aab77d57a8850082258d814c0fe77b2eefcf3)
@@ -66,8 +66,17 @@
 	pipefs_dentry_type_t type;
 	unsigned lnkcnt;	/**< Link count. */
+	/* Following is for nodes of type PIPEFS_FILE */
+	aoff64_t start;		/**< File offset where first data block resides */
 	size_t size;		/**< File size if type is PIPEFS_FILE. */
-	void *data;		/**< File content's if type is PIPEFS_FILE. */
-	link_t cs_head;		/**< Head of child's siblings list. */
+	link_t data_head;	/**< Head of data blocks list for PIPEFS_FILE. */
+	/* This is for directory */
+	link_t cs_head;		/**< Head of child's siblings list. */	
 } pipefs_node_t;
+
+typedef struct pipefs_data_block {
+	link_t link;		/**< Linkage for the list of data blocks */
+	size_t size;		/**< Size of this block */
+	void *data;			/**< Data for this block */
+} pipefs_data_block_t;
 
 extern fs_reg_t pipefs_reg;
Index: uspace/srv/fs/pipefs/pipefs_ops.c
===================================================================
--- uspace/srv/fs/pipefs/pipefs_ops.c	(revision 5bd4f2cdcf5b1214b80769737edcc5abdd052fc9)
+++ uspace/srv/fs/pipefs/pipefs_ops.c	(revision 8d1aab77d57a8850082258d814c0fe77b2eefcf3)
@@ -190,7 +190,13 @@
 	}
 
-	if (nodep->data) {
+	while (!list_empty(&nodep->data_head)) {
 		assert(nodep->type == PIPEFS_FILE);
-		free(nodep->data);
+		
+		pipefs_data_block_t *data_block = list_get_instance(nodep->data_head.next,
+		    pipefs_data_block_t, link);
+		
+		list_remove(&data_block->link);
+		free(data_block->data);
+		free(data_block);
 	}
 	free(nodep->bp);
@@ -212,6 +218,7 @@
 	nodep->type = PIPEFS_NONE;
 	nodep->lnkcnt = 0;
+	nodep->start = 0;
 	nodep->size = 0;
-	nodep->data = NULL;
+	list_initialize(&nodep->data_head);
 	link_initialize(&nodep->nh_link);
 	list_initialize(&nodep->cs_head);
@@ -536,7 +543,71 @@
 	size_t bytes;
 	if (nodep->type == PIPEFS_FILE) {
-		bytes = min(nodep->size - pos, size);
-		(void) async_data_read_finalize(callid, nodep->data + pos,
-		    bytes);
+		/*
+		 * Check if we still have the requested data.
+		 * This may happen if the client seeked backwards
+		 */
+		if (pos < nodep->start) {
+			ipc_answer_0(callid, ENOTSUP);
+			ipc_answer_0(rid, ENOTSUP);
+			return;
+		}
+		
+		/*
+		 * Free all data blocks that end before pos.
+		 * This is in case the client seeked forward 
+		 */
+		while (!list_empty(&nodep->data_head)) {
+			pipefs_data_block_t *data_block =
+			    list_get_instance(nodep->data_head.next,
+			        pipefs_data_block_t, link);
+		
+			aoff64_t block_end = nodep->start + data_block->size;
+			
+			if (block_end > pos) {
+				break;
+			}
+			
+			list_remove(&data_block->link);
+			free(data_block->data);
+			free(data_block);
+			nodep->start = block_end;
+		}
+		
+		if (!list_empty(&nodep->data_head)) {
+			/* We have data block, so let's return its portion after pos */
+			pipefs_data_block_t *data_block =
+			    list_get_instance(nodep->data_head.next,
+			        pipefs_data_block_t, link);
+			
+			assert(nodep->start <= pos);
+			
+			aoff64_t block_end = nodep->start + data_block->size;
+			size_t block_offset = pos - nodep->start;
+			
+			assert(block_end > pos);
+			
+			bytes = min(block_end - pos, size);
+			(void) async_data_read_finalize(callid,
+			    data_block->data + block_offset,
+			    bytes);
+			
+			if (nodep->start + block_offset + bytes == block_end) {
+				/* Free the data block - it was fully read */
+				list_remove(&data_block->link);
+				free(data_block->data);
+				free(data_block);
+				nodep->start = block_end;
+			}
+		}
+		else {
+			/*
+			 * there is no data
+			 * TODO implement waiting for the data
+			 * and remove this else clause
+			 */
+			ipc_answer_0(callid, ENOTSUP);
+			ipc_answer_1(rid, ENOTSUP, 0);
+			return;
+		}
 	} else {
 		pipefs_dentry_t *dentryp;
@@ -610,21 +681,18 @@
 
 	/*
-	 * Check whether the file needs to grow.
-	 */
-	if (pos + size <= nodep->size) {
-		/* The file size is not changing. */
-		(void) async_data_write_finalize(callid, nodep->data + pos, size);
-		ipc_answer_2(rid, EOK, size, nodep->size);
-		return;
-	}
-	size_t delta = (pos + size) - nodep->size;
-	/*
-	 * At this point, we are deliberately extremely straightforward and
-	 * simply realloc the contents of the file on every write that grows the
-	 * file. In the end, the situation might not be as bad as it may look:
-	 * our heap allocator can save us and just grow the block whenever
-	 * possible.
-	 */
-	void *newdata = realloc(nodep->data, nodep->size + delta);
+	 * Check whether we are writing to the end
+	 */
+	if (pos != nodep->size) {
+		ipc_answer_0(callid, ENOTSUP);
+		ipc_answer_2(rid, EOK, 0, nodep->size);
+		return;
+	}
+	
+	/*
+	 * Allocate a buffer for the new data.
+	 * Currently we accept any size, create a data block from this
+	 * and append it to the end of a file
+	 */
+	void *newdata = malloc(size);
 	if (!newdata) {
 		ipc_answer_0(callid, ENOMEM);
@@ -632,9 +700,31 @@
 		return;
 	}
-	/* Clear any newly allocated memory in order to emulate gaps. */
-	memset(newdata + nodep->size, 0, delta);
-	nodep->size += delta;
-	nodep->data = newdata;
-	(void) async_data_write_finalize(callid, nodep->data + pos, size);
+	
+	pipefs_data_block_t *newblock = malloc(sizeof(pipefs_data_block_t));
+	
+	if (!newblock) {
+		free(newdata);
+		ipc_answer_0(callid, ENOMEM);
+		ipc_answer_2(rid, EOK, 0, nodep->size);
+		return;
+	}
+	
+	int rc = async_data_write_finalize(callid, newdata, size);
+	
+	if (rc != EOK) {
+		free(newblock);
+		free(newdata);
+		ipc_answer_0(callid, rc);
+		ipc_answer_2(rid, EOK, 0, nodep->size);
+		return;
+	}
+	
+	link_initialize(&newblock->link);
+	newblock->size = size;
+	newblock->data = newdata;
+	list_append(&newblock->link, &nodep->data_head);
+	
+	nodep->size += size;
+	
 	ipc_answer_2(rid, EOK, size, nodep->size);
 }
@@ -642,48 +732,8 @@
 void pipefs_truncate(ipc_callid_t rid, ipc_call_t *request)
 {
-	devmap_handle_t devmap_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));
-	
-	/*
-	 * Lookup the respective PIPEFS node.
-	 */
-	unsigned long key[] = {
-		[NODES_KEY_DEV] = devmap_handle,
-		[NODES_KEY_INDEX] = index
-	};
-	link_t *hlp = hash_table_find(&nodes, key);
-	if (!hlp) {
-		ipc_answer_0(rid, ENOENT);
-		return;
-	}
-	pipefs_node_t *nodep = hash_table_get_instance(hlp, pipefs_node_t,
-	    nh_link);
-	
-	if (size == nodep->size) {
-		ipc_answer_0(rid, EOK);
-		return;
-	}
-	
-	if (size > SIZE_MAX) {
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	void *newdata = realloc(nodep->data, size);
-	if (!newdata) {
-		ipc_answer_0(rid, ENOMEM);
-		return;
-	}
-	
-	if (size > nodep->size) {
-		size_t delta = size - nodep->size;
-		memset(newdata + nodep->size, 0, delta);
-	}
-	
-	nodep->size = size;
-	nodep->data = newdata;
-	ipc_answer_0(rid, EOK);
+	/*
+	 * PIPEFS does not support resizing of files
+	 */
+	ipc_answer_0(rid, ENOTSUP);
 }
 
