Index: uspace/lib/block/block.c
===================================================================
--- uspace/lib/block/block.c	(revision 2463df96bddf2aaf81fa87e49bc02ae36dad068d)
+++ uspace/lib/block/block.c	(revision dd8b6a87925c4db039bcd5d96da488ee67d92e29)
@@ -55,4 +55,6 @@
 #include "block.h"
 
+#define MAX_WRITE_RETRIES 10
+
 /** Lock protecting the device connection list */
 static FIBRIL_MUTEX_INITIALIZE(dcl_lock);
@@ -79,4 +81,5 @@
 	void *bb_buf;
 	aoff64_t bb_addr;
+	aoff64_t pblocks;    /**< Number of physical blocks */
 	size_t pblock_size;  /**< Physical block size. */
 	cache_t *cache;
@@ -103,5 +106,5 @@
 
 static int devcon_add(service_id_t service_id, async_sess_t *sess,
-    size_t bsize, bd_t *bd)
+    size_t bsize, aoff64_t dev_size, bd_t *bd)
 {
 	devcon_t *devcon;
@@ -118,4 +121,5 @@
 	devcon->bb_addr = 0;
 	devcon->pblock_size = bsize;
+	devcon->pblocks = dev_size;
 	devcon->cache = NULL;
 	
@@ -164,6 +168,7 @@
 		return rc;
 	}
-	
-	rc = devcon_add(service_id, sess, bsize, bd);
+
+	aoff64_t dev_size;
+	rc = bd_get_num_blocks(bd, &dev_size);
 	if (rc != EOK) {
 		bd_close(bd);
@@ -172,4 +177,11 @@
 	}
 	
+	rc = devcon_add(service_id, sess, bsize, dev_size, bd);
+	if (rc != EOK) {
+		bd_close(bd);
+		async_hangup(sess);
+		return rc;
+	}
+	
 	return EOK;
 }
@@ -182,4 +194,6 @@
 	if (devcon->cache)
 		(void) block_cache_fini(service_id);
+	
+	(void)bd_sync_cache(devcon->bd, 0, 0);
 	
 	devcon_remove(devcon);
@@ -349,4 +363,5 @@
 	fibril_mutex_initialize(&b->lock);
 	b->refcnt = 1;
+	b->write_failures = 0;
 	b->dirty = false;
 	b->toxic = false;
@@ -373,5 +388,5 @@
 	block_t *b;
 	link_t *link;
-
+	aoff64_t p_ba;
 	int rc;
 	
@@ -382,4 +397,15 @@
 	
 	cache = devcon->cache;
+
+	/* Check whether the logical block (or part of it) is beyond
+	 * the end of the device or not.
+	 */
+	p_ba = ba_ltop(devcon, ba);
+	p_ba += cache->blocks_cluster;
+	if (p_ba >= devcon->pblocks) {
+		/* This request cannot be satisfied */
+		return EIO;
+	}
+
 
 retry:
@@ -458,7 +484,17 @@
 					 * another block next time.
 					 */
-					fibril_mutex_unlock(&b->lock);
-					goto retry;
-				}
+					if (b->write_failures < MAX_WRITE_RETRIES) {
+						b->write_failures++;
+						fibril_mutex_unlock(&b->lock);
+						goto retry;
+					} else {
+						printf("Too many errors writing block %"
+				    		    PRIuOFF64 "from device handle %" PRIun "\n"
+						    "SEVERE DATA LOSS POSSIBLE\n",
+				    		    b->lba, devcon->service_id);
+					}
+				} else
+					b->write_failures = 0;
+
 				b->dirty = false;
 				if (!fibril_mutex_trylock(&cache->lock)) {
@@ -577,4 +613,6 @@
 		rc = write_blocks(devcon, block->pba, cache->blocks_cluster,
 		    block->data, block->size);
+		if (rc == EOK)
+			block->write_failures = 0;
 		block->dirty = false;
 	}
@@ -602,7 +640,16 @@
 				 */
 				block->refcnt++;
-				fibril_mutex_unlock(&block->lock);
-				fibril_mutex_unlock(&cache->lock);
-				goto retry;
+
+				if (block->write_failures < MAX_WRITE_RETRIES) {
+					block->write_failures++;
+					fibril_mutex_unlock(&block->lock);
+					fibril_mutex_unlock(&cache->lock);
+					goto retry;
+				} else {
+					printf("Too many errors writing block %"
+				            PRIuOFF64 "from device handle %" PRIun "\n"
+					    "SEVERE DATA LOSS POSSIBLE\n",
+				    	    block->lba, devcon->service_id);
+				}
 			}
 			/*
@@ -770,5 +817,5 @@
 	devcon_t *devcon = devcon_search(service_id);
 	assert(devcon);
-	
+
 	return bd_get_num_blocks(devcon->bd, nblocks);
 }
@@ -832,26 +879,14 @@
  *
  * @return Allocated TOC structure.
- * @return NULL on failure.
- *
- */
-toc_block_t *block_get_toc(service_id_t service_id, uint8_t session)
+ * @return EOK on success or negative error code.
+ *
+ */
+int block_read_toc(service_id_t service_id, uint8_t session, void *buf,
+    size_t bufsize)
 {
 	devcon_t *devcon = devcon_search(service_id);
-	toc_block_t *toc = NULL;
-	int rc;
-	
-	assert(devcon);
-	
-	toc = (toc_block_t *) malloc(sizeof(toc_block_t));
-	if (toc == NULL)
-		return NULL;
-	
-	rc = bd_read_toc(devcon->bd, session, toc, sizeof(toc_block_t));
-	if (rc != EOK) {
-		free(toc);
-		return NULL;
-	}
-	
-	return toc;
+	
+	assert(devcon);
+	return bd_read_toc(devcon->bd, session, buf, bufsize);
 }
 
