Index: cpukit/libblock/Makefile.am
===================================================================
--- cpukit/libblock/Makefile.am	(revision 2c6cc3c0de172734b30c03b9ef226f4f27055d21)
+++ cpukit/libblock/Makefile.am	(revision 73c09b3b8efc52831e80295e010fd7bfbd8c4b0c)
@@ -9,4 +9,5 @@
     src/blkdev-ops.c \
     src/diskdevs.c \
+    src/diskdevs-init.c \
     src/flashdisk.c \
     src/ramdisk-driver.c \
Index: cpukit/libblock/include/rtems/bdbuf.h
===================================================================
--- cpukit/libblock/include/rtems/bdbuf.h	(revision 2c6cc3c0de172734b30c03b9ef226f4f27055d21)
+++ cpukit/libblock/include/rtems/bdbuf.h	(revision 73c09b3b8efc52831e80295e010fd7bfbd8c4b0c)
@@ -142,5 +142,5 @@
  * to another requester until released back to the cache.  The same goes to a
  * buffer in the transfer state.  The transfer state means being read or
- * written.  If the file system has modifed the block and releases it as
+ * written.  If the file system has modified the block and releases it as
  * modified it placed on the cache's modified list and a hold timer
  * initialised.  The buffer is held for the hold time before being written to
@@ -463,5 +463,5 @@
 /**
  * Get block buffer for data to be written into. The buffers is set to the
- * access or modifed access state. If the buffer is in the cache and modified
+ * access or modified access state. If the buffer is in the cache and modified
  * the state is access modified else the state is access. This buffer contents
  * are not initialised if the buffer is not already in the cache. If the block
@@ -499,5 +499,5 @@
  * Get the block buffer and if not already in the cache read from the disk. If
  * specified block already cached return. The buffer is set to the access or
- * modifed access state. If the buffer is in the cache and modified the state
+ * modified access state. If the buffer is in the cache and modified the state
  * is access modified else the state is access. If block is already being read
  * from disk for being written to disk this call blocks. If the buffer is
@@ -602,5 +602,5 @@
  * Synchronize all modified buffers for this device with the disk and wait
  * until the transfers have completed. The sync mutex for the cache is locked
- * stopping the addition of any further modifed buffers. It is only the
+ * stopping the addition of any further modified buffers. It is only the
  * currently modified buffers that are written.
  *
@@ -636,6 +636,5 @@
  * @brief Sets the block size of a disk device.
  *
- * This will also change the block_to_media_block_shift and bds_per_group
- * fields of the disk device.
+ * This will set the block size derived fields of the disk device.
  *
  * Before you can use this function, the rtems_bdbuf_init() routine must be
Index: cpukit/libblock/include/rtems/diskdevs.h
===================================================================
--- cpukit/libblock/include/rtems/diskdevs.h	(revision 2c6cc3c0de172734b30c03b9ef226f4f27055d21)
+++ cpukit/libblock/include/rtems/diskdevs.h	(revision 73c09b3b8efc52831e80295e010fd7bfbd8c4b0c)
@@ -93,20 +93,28 @@
 
   /**
-   * @brief Start block number.
-   *
-   * Equals zero for physical devices.  It is a block offset to the related
-   * physical device for logical device.
+   * @brief Start media block number.
+   *
+   * Equals zero for physical devices.  It is a media block offset to the
+   * related physical device for logical device.
    */
   rtems_blkdev_bnum start;
 
   /**
-   * @brief Size of the physical or logical disk in blocks.
+   * @brief Size of the physical or logical disk in media blocks.
    */
   rtems_blkdev_bnum size;
 
   /**
-   * @brief Device block size in bytes.
-   *
-   * This is the minimum transfer unit.  It must be positive.
+   * @brief Media block size in bytes.
+   *
+   * This is the media transfer unit the hardware defaults to.
+   */
+  uint32_t media_block_size;
+
+  /**
+   * @brief Block size in bytes.
+   *
+   * This is the minimum transfer unit.  It may be a multiple of the media
+   * block size. It must be positive.
    *
    * @see rtems_bdbuf_set_block_size().
@@ -115,9 +123,16 @@
 
   /**
-   * @brief Device media block size in bytes.
-   *
-   * This is the media transfer unit the hardware defaults to.
-   */
-  uint32_t media_block_size;
+   * @brief Block count.
+   *
+   * @see rtems_bdbuf_set_block_size().
+   */
+  rtems_blkdev_bnum block_count;
+
+  /**
+   * @brief Media blocks per device blocks.
+   *
+   * @see rtems_bdbuf_set_block_size().
+   */
+  uint32_t media_blocks_per_block;
 
   /**
@@ -260,5 +275,5 @@
  * A logical disk manages a subset of consecutive blocks contained in the
  * physical disk with identifier @a phys.  The start block index of the logical
- * disk device is @a begin_block.  The block count of the logcal disk will be
+ * disk device is @a block_begin.  The block count of the logcal disk will be
  * @a block_count.  The blocks must be within the range of blocks managed by
  * the associated physical disk device.  A device node will be registered in
@@ -279,5 +294,5 @@
   dev_t dev,
   dev_t phys,
-  rtems_blkdev_bnum begin_block,
+  rtems_blkdev_bnum block_begin,
   rtems_blkdev_bnum block_count,
   const char *name
@@ -374,4 +389,21 @@
 rtems_disk_device *rtems_disk_next(dev_t dev);
 
+/* Internal function, do not use */
+rtems_status_code rtems_disk_init_phys(
+  rtems_disk_device *dd,
+  uint32_t block_size,
+  rtems_blkdev_bnum block_count,
+  rtems_block_device_ioctl handler,
+  void *driver_data
+);
+
+/* Internal function, do not use */
+rtems_status_code rtems_disk_init_log(
+  rtems_disk_device *dd,
+  rtems_disk_device *phys_dd,
+  rtems_blkdev_bnum block_begin,
+  rtems_blkdev_bnum block_count
+);
+
 #ifdef __cplusplus
 }
Index: cpukit/libblock/src/bdbuf.c
===================================================================
--- cpukit/libblock/src/bdbuf.c	(revision 2c6cc3c0de172734b30c03b9ef226f4f27055d21)
+++ cpukit/libblock/src/bdbuf.c	(revision 73c09b3b8efc52831e80295e010fd7bfbd8c4b0c)
@@ -1755,18 +1755,21 @@
                              rtems_blkdev_bnum       *media_block_ptr)
 {
-  /*
-   * Compute the media block number. Drivers work with media block number not
-   * the block number a BD may have as this depends on the block size set by
-   * the user.
-   */
-  rtems_blkdev_bnum mb = rtems_bdbuf_media_block (dd, block);
-  if (mb >= dd->size)
-  {
-    return RTEMS_INVALID_ID;
-  }
-
-  *media_block_ptr = mb + dd->start;
-
-  return RTEMS_SUCCESSFUL;
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  if (block < dd->block_count)
+  {
+    /*
+     * Compute the media block number. Drivers work with media block number not
+     * the block number a BD may have as this depends on the block size set by
+     * the user.
+     */
+    *media_block_ptr = rtems_bdbuf_media_block (dd, block) + dd->start;
+  }
+  else
+  {
+    sc = RTEMS_INVALID_ID;
+  }
+
+  return sc;
 }
 
@@ -2910,4 +2913,6 @@
 
       dd->block_size = block_size;
+      dd->block_count = dd->size / media_blocks_per_block;
+      dd->media_blocks_per_block = media_blocks_per_block;
       dd->block_to_media_block_shift = block_to_media_block_shift;
       dd->bds_per_group = bds_per_group;
Index: cpukit/libblock/src/blkdev-imfs.c
===================================================================
--- cpukit/libblock/src/blkdev-imfs.c	(revision 2c6cc3c0de172734b30c03b9ef226f4f27055d21)
+++ cpukit/libblock/src/blkdev-imfs.c	(revision 73c09b3b8efc52831e80295e010fd7bfbd8c4b0c)
@@ -270,44 +270,34 @@
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
-
-  if (block_count > 0) {
-    rtems_blkdev_imfs_context *ctx = calloc(1, sizeof(*ctx));
-
-    if (ctx != NULL) {
-      rtems_disk_device *dd = &ctx->dd;
-
-      ctx->fd = -1;
-
-      dd->phys_dev = dd;
-      dd->size = block_count;
-      dd->media_block_size = block_size;
-      dd->ioctl = handler;
-      dd->driver_data = driver_data;
-
-      if ((*handler)(dd, RTEMS_BLKIO_CAPABILITIES, &dd->capabilities) != 0) {
-        dd->capabilities = 0;
-      }
-
-      sc = rtems_bdbuf_set_block_size(dd, block_size);
-      if (sc == RTEMS_SUCCESSFUL) {
-        int rv = IMFS_make_generic_node(
-          device,
-          S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO,
-          &rtems_blkdev_imfs_control,
-          ctx
-        );
-
-        if (rv != 0) {
-          free(ctx);
-          sc = RTEMS_UNSATISFIED;
-        }
-      } else {
+  rtems_blkdev_imfs_context *ctx = malloc(sizeof(*ctx));
+
+  if (ctx != NULL) {
+    sc = rtems_disk_init_phys(
+      &ctx->dd,
+      block_size,
+      block_count,
+      handler,
+      driver_data
+    );
+
+    ctx->fd = -1;
+
+    if (sc == RTEMS_SUCCESSFUL) {
+      int rv = IMFS_make_generic_node(
+        device,
+        S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO,
+        &rtems_blkdev_imfs_control,
+        ctx
+      );
+
+      if (rv != 0) {
         free(ctx);
-      }
-    } else {
-      sc = RTEMS_NO_MEMORY;
-    }
-  } else {
-    sc = RTEMS_INVALID_NUMBER;
+        sc = RTEMS_UNSATISFIED;
+      }
+    } else {
+      free(ctx);
+    }
+  } else {
+    sc = RTEMS_NO_MEMORY;
   }
 
@@ -331,22 +321,19 @@
     rv = fstat(fd, &st);
     if (rv == 0 && S_ISBLK(st.st_mode)) {
-      rtems_disk_device *dd;
-
-      rv = rtems_disk_fd_get_disk_device(fd, &dd);
+      rtems_disk_device *phys_dd;
+
+      rv = rtems_disk_fd_get_disk_device(fd, &phys_dd);
       if (rv == 0) {
-        rtems_blkdev_bnum device_block_count = rtems_disk_get_block_count(dd);
-
-        if (
-          block_begin < device_block_count
-            && block_count > 0
-            && block_count <= device_block_count - block_begin
-        ) {
-          rtems_blkdev_imfs_context *ctx = malloc(sizeof(*ctx));
-
-          if (ctx != NULL) {
-            memcpy(&ctx->dd, dd, sizeof(ctx->dd));
-
-            ctx->dd.start = block_begin;
-            ctx->dd.size = block_count;
+        rtems_blkdev_imfs_context *ctx = malloc(sizeof(*ctx));
+
+        if (ctx != NULL) {
+          sc = rtems_disk_init_log(
+            &ctx->dd,
+            phys_dd,
+            block_begin,
+            block_count
+          );
+
+          if (sc == RTEMS_SUCCESSFUL) {
             ctx->fd = fd;
 
@@ -363,8 +350,8 @@
             }
           } else {
-            sc = RTEMS_NO_MEMORY;
+            free(ctx);
           }
         } else {
-          sc = RTEMS_INVALID_NUMBER;
+          sc = RTEMS_NO_MEMORY;
         }
       } else {
Index: cpukit/libblock/src/diskdevs-init.c
===================================================================
--- cpukit/libblock/src/diskdevs-init.c	(revision 73c09b3b8efc52831e80295e010fd7bfbd8c4b0c)
+++ cpukit/libblock/src/diskdevs-init.c	(revision 73c09b3b8efc52831e80295e010fd7bfbd8c4b0c)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems/blkdev.h>
+#include <rtems/bdbuf.h>
+
+rtems_status_code rtems_disk_init_phys(
+  rtems_disk_device *dd,
+  uint32_t block_size,
+  rtems_blkdev_bnum block_count,
+  rtems_block_device_ioctl handler,
+  void *driver_data
+)
+{
+  rtems_status_code sc;
+
+  dd = memset(dd, 0, sizeof(*dd));
+
+  dd->phys_dev = dd;
+  dd->size = block_count;
+  dd->media_block_size = block_size;
+  dd->ioctl = handler;
+  dd->driver_data = driver_data;
+
+  if (block_count > 0) {
+    if ((*handler)(dd, RTEMS_BLKIO_CAPABILITIES, &dd->capabilities) != 0) {
+      dd->capabilities = 0;
+    }
+
+    sc = rtems_bdbuf_set_block_size(dd, block_size);
+  } else {
+    sc = RTEMS_INVALID_NUMBER;
+  }
+
+  return sc;
+}
+
+rtems_status_code rtems_disk_init_log(
+  rtems_disk_device *dd,
+  rtems_disk_device *phys_dd,
+  rtems_blkdev_bnum block_begin,
+  rtems_blkdev_bnum block_count
+)
+{
+  rtems_status_code sc;
+
+  dd = memset(dd, 0, sizeof(*dd));
+
+  dd->phys_dev = phys_dd;
+  dd->start = block_begin;
+  dd->size = block_count;
+  dd->media_block_size = phys_dd->media_block_size;
+  dd->ioctl = phys_dd->ioctl;
+  dd->driver_data = phys_dd->driver_data;
+
+  if (phys_dd->phys_dev == phys_dd) {
+    rtems_blkdev_bnum phys_block_count = phys_dd->size;
+
+    if (
+      block_begin < phys_block_count
+        && block_count > 0
+        && block_count <= phys_block_count - block_begin
+    ) {
+      sc = rtems_bdbuf_set_block_size(dd, phys_dd->media_block_size);
+    } else {
+      sc = RTEMS_INVALID_NUMBER;
+    }
+  } else {
+    sc = RTEMS_INVALID_ID;
+  }
+
+  return sc;
+}
Index: cpukit/libblock/src/diskdevs.c
===================================================================
--- cpukit/libblock/src/diskdevs.c	(revision 2c6cc3c0de172734b30c03b9ef226f4f27055d21)
+++ cpukit/libblock/src/diskdevs.c	(revision 73c09b3b8efc52831e80295e010fd7bfbd8c4b0c)
@@ -11,5 +11,5 @@
  * Author: Victor V. Vengerov <vvv@oktet.ru>
  *
- * Copyright (c) 2009 embedded brains GmbH.
+ * Copyright (c) 2009-2012 embedded brains GmbH.
  */
 
@@ -171,5 +171,10 @@
 
 static rtems_status_code
-create_disk(dev_t dev, const char *name, rtems_disk_device **dd_ptr)
+create_disk(
+  dev_t dev,
+  const char *name,
+  rtems_disk_device **dd_ptr,
+  char **alloc_name_ptr
+)
 {
   rtems_disk_device **dd_entry = create_disk_table_entry(dev);
@@ -208,11 +213,7 @@
   }
 
-  dd->dev = dev;
-  dd->name = alloc_name;
-  dd->uses = 0;
-  dd->deleted = false;
-
   *dd_entry = dd;
   *dd_ptr = dd;
+  *alloc_name_ptr = alloc_name;
 
   return RTEMS_SUCCESSFUL;
@@ -239,4 +240,5 @@
   rtems_disk_device *dd = NULL;
   rtems_status_code sc = RTEMS_SUCCESSFUL;
+  char *alloc_name = NULL;
 
   if (handler == NULL) {
@@ -249,5 +251,5 @@
   }
 
-  sc = create_disk(dev, name, &dd);
+  sc = create_disk(dev, name, &dd, &alloc_name);
   if (sc != RTEMS_SUCCESSFUL) {
     disk_unlock();
@@ -256,16 +258,15 @@
   }
 
-  dd->phys_dev = dd;
-  dd->start = 0;
-  dd->size = block_count;
-  dd->media_block_size = block_size;
-  dd->ioctl = handler;
-  dd->driver_data = driver_data;
-
-  if ((*handler)(dd, RTEMS_BLKIO_CAPABILITIES, &dd->capabilities) < 0) {
-    dd->capabilities = 0;
-  }
-
-  sc = rtems_bdbuf_set_block_size(dd, block_size);
+  sc = rtems_disk_init_phys(
+    dd,
+    block_size,
+    block_count,
+    handler,
+    driver_data
+  );
+
+  dd->dev = dev;
+  dd->name = alloc_name;
+
   if (sc != RTEMS_SUCCESSFUL) {
     dd->ioctl = null_handler;
@@ -290,5 +291,5 @@
   dev_t dev,
   dev_t phys,
-  rtems_blkdev_bnum begin_block,
+  rtems_blkdev_bnum block_begin,
   rtems_blkdev_bnum block_count,
   const char *name
@@ -296,7 +297,7 @@
 {
   rtems_status_code sc = RTEMS_SUCCESSFUL;
-  rtems_disk_device *physical_disk = NULL;
+  rtems_disk_device *phys_dd = NULL;
   rtems_disk_device *dd = NULL;
-  rtems_blkdev_bnum end_block = begin_block + block_count;
+  char *alloc_name = NULL;
 
   sc = disk_lock();
@@ -305,6 +306,6 @@
   }
 
-  physical_disk = get_disk_entry(phys, true);
-  if (physical_disk == NULL || !is_physical_disk(physical_disk)) {
+  phys_dd = get_disk_entry(phys, true);
+  if (phys_dd == NULL) {
     disk_unlock();
 
@@ -312,32 +313,30 @@
   }
 
-  if (
-    begin_block >= physical_disk->size
-      || end_block <= begin_block
-      || end_block > physical_disk->size
-  ) {
+  sc = create_disk(dev, name, &dd, &alloc_name);
+  if (sc != RTEMS_SUCCESSFUL) {
     disk_unlock();
 
-    return RTEMS_INVALID_NUMBER;
-  }
-
-  sc = create_disk(dev, name, &dd);
-  if (sc != RTEMS_SUCCESSFUL) {
+    return sc;
+  }
+
+  sc = rtems_disk_init_log(
+    dd,
+    phys_dd,
+    block_begin,
+    block_count
+  );
+
+  dd->dev = dev;
+  dd->name = alloc_name;
+
+  ++phys_dd->uses;
+
+  if (sc != RTEMS_SUCCESSFUL) {
+    dd->ioctl = null_handler;
+    rtems_disk_delete(dev);
     disk_unlock();
 
     return sc;
   }
-
-  dd->phys_dev = physical_disk;
-  dd->start = begin_block;
-  dd->size = block_count;
-  dd->block_size = physical_disk->block_size;
-  dd->media_block_size = physical_disk->media_block_size;
-  dd->block_to_media_block_shift = physical_disk->block_to_media_block_shift;
-  dd->bds_per_group = physical_disk->bds_per_group;
-  dd->ioctl = physical_disk->ioctl;
-  dd->driver_data = physical_disk->driver_data;
-
-  ++physical_disk->uses;
 
   disk_unlock();
