Index: uspace/lib/libblock/libblock.c
===================================================================
--- uspace/lib/libblock/libblock.c	(revision 08232eec7477aa13695d471714768b19b5d6d270)
+++ uspace/lib/libblock/libblock.c	(revision ed90317444652a29e89501a128d66020aaea52b5)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Jakub Jermar 
- * Copyright (c) 2008 Martin Decky 
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2008 Martin Decky
  * All rights reserved.
  *
@@ -52,4 +52,6 @@
 #include <macros.h>
 #include <mem.h>
+#include <sys/typefmt.h>
+#include <stacktrace.h>
 
 /** Lock protecting the device connection list */
@@ -79,13 +81,13 @@
 	size_t comm_size;
 	void *bb_buf;
-	bn_t bb_addr;
+	aoff64_t bb_addr;
 	size_t pblock_size;		/**< Physical block size. */
 	cache_t *cache;
 } devcon_t;
 
-static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
-static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt);
+static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt);
+static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt);
 static int get_block_size(int dev_phone, size_t *bsize);
-static int get_num_blocks(int dev_phone, bn_t *nblocks);
+static int get_num_blocks(int dev_phone, aoff64_t *nblocks);
 
 static devcon_t *devcon_search(dev_handle_t dev_handle)
@@ -198,4 +200,7 @@
 	assert(devcon);
 	
+	if (devcon->cache)
+		(void) block_cache_fini(dev_handle);
+
 	devcon_remove(devcon);
 
@@ -203,9 +208,4 @@
 		free(devcon->bb_buf);
 
-	if (devcon->cache) {
-		hash_table_destroy(&devcon->cache->block_hash);
-		free(devcon->cache);
-	}
-
 	munmap(devcon->comm_area, devcon->comm_size);
 	ipc_hangup(devcon->dev_phone);
@@ -214,5 +214,5 @@
 }
 
-int block_bb_read(dev_handle_t dev_handle, bn_t ba)
+int block_bb_read(dev_handle_t dev_handle, aoff64_t ba)
 {
 	void *bb_buf;
@@ -305,4 +305,47 @@
 }
 
+int block_cache_fini(dev_handle_t dev_handle)
+{
+	devcon_t *devcon = devcon_search(dev_handle);
+	cache_t *cache;
+	int rc;
+
+	if (!devcon)
+		return ENOENT;
+	if (!devcon->cache)
+		return EOK;
+	cache = devcon->cache;
+	
+	/*
+	 * We are expecting to find all blocks for this device handle on the
+	 * free list, i.e. the block reference count should be zero. Do not
+	 * bother with the cache and block locks because we are single-threaded.
+	 */
+	while (!list_empty(&cache->free_head)) {
+		block_t *b = list_get_instance(cache->free_head.next,
+		    block_t, free_link);
+
+		list_remove(&b->free_link);
+		if (b->dirty) {
+			memcpy(devcon->comm_area, b->data, b->size);
+			rc = write_blocks(devcon, b->boff, 1);
+			if (rc != EOK)
+				return rc;
+		}
+
+		unsigned long key = b->boff;
+		hash_table_remove(&cache->block_hash, &key, 1);
+		
+		free(b->data);
+		free(b);
+	}
+
+	hash_table_destroy(&cache->block_hash);
+	devcon->cache = NULL;
+	free(cache);
+
+	return EOK;
+}
+
 #define CACHE_LO_WATERMARK	10	
 #define CACHE_HI_WATERMARK	20	
@@ -339,5 +382,5 @@
  * @return			EOK on success or a negative error code.
  */
-int block_get(block_t **block, dev_handle_t dev_handle, bn_t boff, int flags)
+int block_get(block_t **block, dev_handle_t dev_handle, aoff64_t boff, int flags)
 {
 	devcon_t *devcon;
@@ -614,8 +657,8 @@
  * @return		EOK on success or a negative return code on failure.
  */
-int block_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen,
-    off_t *pos, void *dst, size_t size)
-{
-	off_t offset = 0;
+int block_seqread(dev_handle_t dev_handle, size_t *bufpos, size_t *buflen,
+    aoff64_t *pos, void *dst, size_t size)
+{
+	size_t offset = 0;
 	size_t left = size;
 	size_t block_size;
@@ -647,5 +690,5 @@
 		}
 		
-		if (*bufpos == (off_t) *buflen) {
+		if (*bufpos == *buflen) {
 			/* Refill the communication buffer with a new block. */
 			int rc;
@@ -675,5 +718,5 @@
  * @return		EOK on success or negative error code on failure.
  */
-int block_read_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt, void *buf)
+int block_read_direct(dev_handle_t dev_handle, aoff64_t ba, size_t cnt, void *buf)
 {
 	devcon_t *devcon;
@@ -703,5 +746,5 @@
  * @return		EOK on success or negative error code on failure.
  */
-int block_write_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt,
+int block_write_direct(dev_handle_t dev_handle, aoff64_t ba, size_t cnt,
     const void *data)
 {
@@ -746,5 +789,5 @@
  * @return		EOK on success or negative error code on failure.
  */
-int block_get_nblocks(dev_handle_t dev_handle, bn_t *nblocks)
+int block_get_nblocks(dev_handle_t dev_handle, aoff64_t *nblocks)
 {
 	devcon_t *devcon;
@@ -765,5 +808,5 @@
  * @return		EOK on success or negative error code on failure.
  */
-static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
+static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
 {
 	int rc;
@@ -772,4 +815,12 @@
 	rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),
 	    UPPER32(ba), cnt);
+	if (rc != EOK) {
+		printf("Error %d reading %d blocks starting at block %" PRIuOFF64
+		    " from device handle %d\n", rc, cnt, ba,
+		    devcon->dev_handle);
+#ifndef NDEBUG
+		stacktrace_print();
+#endif
+	}
 	return rc;
 }
@@ -784,5 +835,5 @@
  * @return		EOK on success or negative error code on failure.
  */
-static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt)
+static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt)
 {
 	int rc;
@@ -791,4 +842,11 @@
 	rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),
 	    UPPER32(ba), cnt);
+	if (rc != EOK) {
+		printf("Error %d writing %d blocks starting at block %" PRIuOFF64
+		    " to device handle %d\n", rc, cnt, ba, devcon->dev_handle);
+#ifndef NDEBUG
+		stacktrace_print();
+#endif
+	}
 	return rc;
 }
@@ -808,5 +866,5 @@
 
 /** Get total number of blocks on block device. */
-static int get_num_blocks(int dev_phone, bn_t *nblocks)
+static int get_num_blocks(int dev_phone, aoff64_t *nblocks)
 {
 	ipcarg_t nb_l, nb_h;
@@ -815,5 +873,5 @@
 	rc = async_req_0_2(dev_phone, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);
 	if (rc == EOK) {
-		*nblocks = (bn_t) MERGE_LOUP32(nb_l, nb_h);
+		*nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);
 	}
 
