Index: uspace/lib/block/libblock.c
===================================================================
--- uspace/lib/block/libblock.c	(revision e28d228b1137cc0cbda02e837ac8fc3747165aff)
+++ uspace/lib/block/libblock.c	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
@@ -66,4 +66,5 @@
 	fibril_mutex_t lock;
 	size_t lblock_size;		/**< Logical block size. */
+	unsigned blocks_cluster;	/**< Physical blocks per block_t */
 	unsigned block_count;		/**< Total number of blocks. */
 	unsigned blocks_cached;		/**< Number of cached blocks. */
@@ -90,4 +91,5 @@
 static int get_block_size(int dev_phone, size_t *bsize);
 static int get_num_blocks(int dev_phone, aoff64_t *nblocks);
+static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba);
 
 static devcon_t *devcon_search(devmap_handle_t devmap_handle)
@@ -259,5 +261,5 @@
 {
 	block_t *b = hash_table_get_instance(item, block_t, hash_link);
-	return b->boff == *key;
+	return b->lba == *key;
 }
 
@@ -292,6 +294,9 @@
 	cache->mode = mode;
 
-	/* No block size translation a.t.m. */
-	assert(cache->lblock_size == devcon->pblock_size);
+	/* Allow 1:1 or small-to-large block size translation */
+	if (cache->lblock_size % devcon->pblock_size != 0)
+		return ENOTSUP;
+
+	cache->blocks_cluster = cache->lblock_size / devcon->pblock_size;
 
 	if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,
@@ -329,10 +334,10 @@
 		if (b->dirty) {
 			memcpy(devcon->comm_area, b->data, b->size);
-			rc = write_blocks(devcon, b->boff, 1);
+			rc = write_blocks(devcon, b->pba, cache->blocks_cluster);
 			if (rc != EOK)
 				return rc;
 		}
 
-		unsigned long key = b->boff;
+		unsigned long key = b->lba;
 		hash_table_remove(&cache->block_hash, &key, 1);
 		
@@ -375,5 +380,5 @@
  * 				block pointer on success.
  * @param devmap_handle		Device handle of the block device.
- * @param boff			Block offset.
+ * @param ba			Block address (logical).
  * @param flags			If BLOCK_FLAGS_NOREAD is specified, block_get()
  * 				will not read the contents of the block from the
@@ -382,5 +387,5 @@
  * @return			EOK on success or a negative error code.
  */
-int block_get(block_t **block, devmap_handle_t devmap_handle, aoff64_t boff, int flags)
+int block_get(block_t **block, devmap_handle_t devmap_handle, aoff64_t ba, int flags)
 {
 	devcon_t *devcon;
@@ -388,5 +393,5 @@
 	block_t *b;
 	link_t *l;
-	unsigned long key = boff;
+	unsigned long key = ba;
 	int rc;
 	
@@ -465,5 +470,6 @@
 				fibril_mutex_lock(&devcon->comm_area_lock);
 				memcpy(devcon->comm_area, b->data, b->size);
-				rc = write_blocks(devcon, b->boff, 1);
+				rc = write_blocks(devcon, b->pba,
+				    cache->blocks_cluster);
 				fibril_mutex_unlock(&devcon->comm_area_lock);
 				if (rc != EOK) {
@@ -495,5 +501,5 @@
 			 */
 			list_remove(&b->free_link);
-			temp_key = b->boff;
+			temp_key = b->lba;
 			hash_table_remove(&cache->block_hash, &temp_key, 1);
 		}
@@ -502,5 +508,6 @@
 		b->devmap_handle = devmap_handle;
 		b->size = cache->lblock_size;
-		b->boff = boff;
+		b->lba = ba;
+		b->pba = ba_ltop(devcon, b->lba);
 		hash_table_insert(&cache->block_hash, &key, &b->hash_link);
 
@@ -519,5 +526,5 @@
 			 */
 			fibril_mutex_lock(&devcon->comm_area_lock);
-			rc = read_blocks(devcon, b->boff, 1);
+			rc = read_blocks(devcon, b->pba, cache->blocks_cluster);
 			memcpy(b->data, devcon->comm_area, cache->lblock_size);
 			fibril_mutex_unlock(&devcon->comm_area_lock);
@@ -580,5 +587,5 @@
 		fibril_mutex_lock(&devcon->comm_area_lock);
 		memcpy(devcon->comm_area, block->data, block->size);
-		rc = write_blocks(devcon, block->boff, 1);
+		rc = write_blocks(devcon, block->pba, cache->blocks_cluster);
 		fibril_mutex_unlock(&devcon->comm_area_lock);
 		block->dirty = false;
@@ -614,5 +621,5 @@
 			 * Take the block out of the cache and free it.
 			 */
-			unsigned long key = block->boff;
+			unsigned long key = block->lba;
 			hash_table_remove(&cache->block_hash, &key, 1);
 			free(block);
@@ -712,5 +719,5 @@
  *
  * @param devmap_handle	Device handle of the block device.
- * @param ba		Address of first block.
+ * @param ba		Address of first block (physical).
  * @param cnt		Number of blocks.
  * @param src		Buffer for storing the data.
@@ -740,5 +747,5 @@
  *
  * @param devmap_handle	Device handle of the block device.
- * @param ba		Address of first block.
+ * @param ba		Address of first block (physical).
  * @param cnt		Number of blocks.
  * @param src		The data to be written.
@@ -879,4 +886,11 @@
 }
 
+/** Convert logical block address to physical block address. */
+static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba)
+{
+	assert(devcon->cache != NULL);
+	return lba * devcon->cache->blocks_cluster;
+}
+
 /** @}
  */
Index: uspace/lib/block/libblock.h
===================================================================
--- uspace/lib/block/libblock.h	(revision e28d228b1137cc0cbda02e837ac8fc3747165aff)
+++ uspace/lib/block/libblock.h	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
@@ -73,6 +73,8 @@
 	/** Handle of the device where the block resides. */
 	devmap_handle_t devmap_handle;
-	/** Block offset on the block device. Counted in 'size'-byte blocks. */
-	aoff64_t boff;
+	/** Logical block address */
+	aoff64_t lba;
+	/** Physical block address */
+	aoff64_t pba;
 	/** Size of the block. */
 	size_t size;
Index: uspace/srv/bd/file_bd/file_bd.c
===================================================================
--- uspace/srv/bd/file_bd/file_bd.c	(revision e28d228b1137cc0cbda02e837ac8fc3747165aff)
+++ uspace/srv/bd/file_bd/file_bd.c	(revision 35537a7e0a8620c3b6050f4f49acfece7b803be1)
@@ -56,5 +56,7 @@
 #define NAME "file_bd"
 
-static const size_t block_size = 512;
+#define DEFAULT_BLOCK_SIZE 512
+
+static size_t block_size;
 static aoff64_t num_blocks;
 static FILE *img;
@@ -63,4 +65,5 @@
 static fibril_mutex_t dev_lock;
 
+static void print_usage(void);
 static int file_bd_init(const char *fname);
 static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall);
@@ -71,20 +74,53 @@
 {
 	int rc;
+	char *image_name;
+	char *device_name;
 
 	printf(NAME ": File-backed block device driver\n");
 
-	if (argc != 3) {
-		printf("Expected two arguments (image name, device name).\n");
+	block_size = DEFAULT_BLOCK_SIZE;
+
+	++argv; --argc;
+	while (*argv != NULL && (*argv)[0] == '-') {
+		/* Option */
+		if (str_cmp(*argv, "-b") == 0) {
+			if (argc < 2) {
+				printf("Argument missing.\n");
+				print_usage();
+				return -1;
+			}
+
+			rc = str_size_t(argv[1], NULL, 10, true, &block_size);
+			if (rc != EOK || block_size == 0) {
+				printf("Invalid block size '%s'.\n", argv[1]);
+				print_usage();
+				return -1;
+			}
+			++argv; --argc;
+		} else {
+			printf("Invalid option '%s'.\n", *argv);
+			print_usage();
+			return -1;
+		}
+		++argv; --argc;
+	}
+
+	if (argc < 2) {
+		printf("Missing arguments.\n");
+		print_usage();
 		return -1;
 	}
 
-	if (file_bd_init(argv[1]) != EOK)
+	image_name = argv[0];
+	device_name = argv[1];
+
+	if (file_bd_init(image_name) != EOK)
 		return -1;
 
-	rc = devmap_device_register(argv[2], &devmap_handle);
+	rc = devmap_device_register(device_name, &devmap_handle);
 	if (rc != EOK) {
 		devmap_hangup_phone(DEVMAP_DRIVER);
-		printf(NAME ": Unable to register device %s.\n",
-			argv[2]);
+		printf(NAME ": Unable to register device '%s'.\n",
+			device_name);
 		return rc;
 	}
@@ -96,4 +132,9 @@
 	/* Not reached */
 	return 0;
+}
+
+static void print_usage(void)
+{
+	printf("Usage: " NAME " [-b <block_size>] <image_file> <device_name>\n");
 }
 
