Index: cpukit/libblock/include/rtems/blkdev.h
===================================================================
--- cpukit/libblock/include/rtems/blkdev.h	(revision 1560d12d0141710c3aa63f3409ce0d0b4a41dc30)
+++ cpukit/libblock/include/rtems/blkdev.h	(revision d61f0a7ba5f9569fea05ce2624c53b8466600e88)
@@ -163,4 +163,5 @@
 #define RTEMS_BLKIO_GETSIZE         _IO('B', 5)
 #define RTEMS_BLKIO_SYNCDEV         _IO('B', 6)
+#define RTEMS_BLKIO_DELETED         _IO('B', 7)
 
 /** @} */
Index: cpukit/libblock/include/rtems/diskdevs.h
===================================================================
--- cpukit/libblock/include/rtems/diskdevs.h	(revision 1560d12d0141710c3aa63f3409ce0d0b4a41dc30)
+++ cpukit/libblock/include/rtems/diskdevs.h	(revision d61f0a7ba5f9569fea05ce2624c53b8466600e88)
@@ -4,5 +4,5 @@
  * @ingroup rtems_disk
  *
- * Block device disk management.
+ * @brief Block device disk management API.
  */
  
@@ -90,5 +90,5 @@
    * @brief Usage counter.
    *
-   * Devices cannot be removed if they are in use.
+   * Devices cannot be deleted if they are in use.
    */
   unsigned uses;
@@ -130,4 +130,10 @@
    */
   void *driver_data;
+
+  /**
+   * @brief Indicates that this disk should be deleted as soon as the last user
+   * releases this disk.
+   */
+  bool deleted;
 };
 
@@ -204,17 +210,25 @@
  * @brief Creates a physical disk with device identifier @a dev.
  *
- * The block size @a block_size must be a power of two.  The disk size @a
- * disk_size is the number of blocks provided by this disk.  The block index
- * starts with zero.  The associated disk device driver will be invoked via the
- * IO control handler @a handler.  A device node will be registered in the file
- * system with absolute path @a name.  This function is usually invoked from a
+ * The block size @a block_size must be positive.  The disk will have
+ * @a block_count blocks.  The block index starts with zero.  The associated disk
+ * device driver will be invoked via the IO control handler @a handler.  A
+ * device node will be registered in the file system with absolute path @a
+ * name, if @a name is not @c NULL.  This function is usually invoked from a
  * block device driver during initialization when a physical device is detected
  * in the system.  The device driver provides an IO control handler to allow
  * block device operations.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NOT_CONFIGURED Cannot lock disk device operation mutex.
+ * @retval RTEMS_INVALID_ADDRESS IO control handler is @c NULL.
+ * @retval RTEMS_INVALID_NUMBER Block size is zero.
+ * @retval RTEMS_NO_MEMORY Not enough memory.
+ * @retval RTEMS_RESOURCE_IN_USE Disk device descriptor is already in use.
+ * @retval RTEMS_UNSATISFIED Cannot create device node.
  */
 rtems_status_code rtems_disk_create_phys(
   dev_t dev,
   uint32_t block_size,
-  rtems_blkdev_bnum disk_size,
+  rtems_blkdev_bnum block_count,
   rtems_block_device_ioctl handler,
   void *driver_data,
@@ -227,15 +241,25 @@
  * 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 start.  The block number of the logcal disk will be @a
- * size.  The blocks must be within the range of blocks managed by the
- * associated physical disk device.  A device node will be registered in the
- * file system with absolute path @a name.  The block size and IO control
- * handler are inherited by the physical disk.
+ * disk device is @a begin_block.  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
+ * the file system with absolute path @a name, if @a name is not @c NULL.  The
+ * block size and IO control handler are inherited by the physical disk.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NOT_CONFIGURED Cannot lock disk device operation mutex.
+ * @retval RTEMS_INVALID_ID Specified physical disk identifier does not
+ * correspond to a physical disk.
+ * @retval RTEMS_INVALID_NUMBER Begin block or block count are out of range.
+ * @retval RTEMS_NO_MEMORY Not enough memory.
+ * @retval RTEMS_RESOURCE_IN_USE Disk device descriptor for logical disk
+ * identifier is already in use.
+ * @retval RTEMS_UNSATISFIED Cannot create device node.
  */
 rtems_status_code rtems_disk_create_log(
   dev_t dev,
   dev_t phys,
-  rtems_blkdev_bnum start,
-  rtems_blkdev_bnum size,
+  rtems_blkdev_bnum begin_block,
+  rtems_blkdev_bnum block_count,
   const char *name
 );
@@ -244,8 +268,15 @@
  * @brief Deletes a physical or logical disk device with identifier @a dev.
  *
- * Disk devices may be deleted if there usage counter (and the usage counters
- * of all contained logical disks devices) equals zero.  When a physical disk
- * device is deleted, all logical disk devices will deleted too.  The
- * corresponding device nodes will be removed from the file system.
+ * Marks the disk device as deleted.  When a physical disk device is deleted,
+ * all corresponding logical disk devices will marked as deleted too.  Disks
+ * that are marked as deleted and have a usage counter of zero will be deleted.
+ * The corresponding device nodes will be removed from the file system.  In
+ * case of a physical disk deletion the IO control handler will be invoked with
+ * a RTEMS_BLKIO_DELETED request.  Disks that are still in use will be deleted
+ * upon release.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ * @retval RTEMS_NOT_CONFIGURED Cannot lock disk device operation mutex.
+ * @retval RTEMS_INVALID_ID No disk for specified device identifier.
  */
 rtems_status_code rtems_disk_delete(dev_t dev);
@@ -255,5 +286,7 @@
  *
  * Increments usage counter by one.  You should release the disk device
- * descriptor with rtems_disk_release().  Returns @c NULL if no corresponding
+ * descriptor with rtems_disk_release().
+ *
+ * @return Pointer to the disk device descriptor or @c NULL if no corresponding
  * disk exists.
  */
@@ -261,7 +294,9 @@
 
 /**
- * @brief Releases the disk device description @a dd.
+ * @brief Releases the disk device descriptor @a dd.
  *
  * Decrements usage counter by one.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
  */
 rtems_status_code rtems_disk_release(rtems_disk_device *dd);
@@ -274,4 +309,30 @@
  * @{
  */
+
+/**
+ * @brief Initializes the disk device management.
+ *
+ * This functions returns successful if the disk device management is already
+ * initialized.  There is no protection against concurrent access.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful initialization.
+ * @retval RTEMS_NO_MEMORY Not enough memory or no semaphore available.
+ * @retval RTEMS_UNSATISFIED Block device buffer initialization failed.
+ */
+rtems_status_code rtems_disk_io_initialize(void);
+
+/**
+ * @brief Releases all resources allocated for disk device management.
+ *
+ * There is no protection against concurrent access.  If parts of the system
+ * are still in use the behaviour is undefined.
+ *
+ * @retval RTEMS_SUCCESSFUL Successful operation.
+ */
+rtems_status_code rtems_disk_io_done(void);
+
+/** @} */
+
+/** @} */
 
 /**
@@ -292,21 +353,4 @@
 rtems_disk_device *rtems_disk_next(dev_t dev);
 
-/**
- * @brief Initializes the disk device management.
- *
- * This functions returns successful if the disk device management is already
- * initialized.  There is no protection against concurrent access.
- */
-rtems_status_code rtems_disk_io_initialize(void);
-
-/**
- * @brief Releases all resources allocated for disk device management.
- */
-rtems_status_code rtems_disk_io_done(void);
-
-/** @} */
-
-/** @} */
-
 #ifdef __cplusplus
 }
Index: cpukit/libblock/include/rtems/ramdisk.h
===================================================================
--- cpukit/libblock/include/rtems/ramdisk.h	(revision 1560d12d0141710c3aa63f3409ce0d0b4a41dc30)
+++ cpukit/libblock/include/rtems/ramdisk.h	(revision d61f0a7ba5f9569fea05ce2624c53b8466600e88)
@@ -75,6 +75,4 @@
  */
 extern size_t rtems_ramdisk_configuration_size;
-
-int ramdisk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
 
 /**
@@ -143,4 +141,6 @@
 extern const rtems_driver_address_table ramdisk_ops;
 
+int ramdisk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
+
 /**
  * @brief Allocates and initializes a RAM disk descriptor.
@@ -154,5 +154,11 @@
  * if no memory is available.
  *
+ * @note
+ * Runtime configuration example:
  * @code
+ * #include <rtems.h>
+ * #include <rtems/libio.h>
+ * #include <rtems/ramdisk.h>
+ *
  * rtems_status_code create_ramdisk(
  *   const char *disk_name_path,
Index: cpukit/libblock/src/diskdevs.c
===================================================================
--- cpukit/libblock/src/diskdevs.c	(revision 1560d12d0141710c3aa63f3409ce0d0b4a41dc30)
+++ cpukit/libblock/src/diskdevs.c	(revision d61f0a7ba5f9569fea05ce2624c53b8466600e88)
@@ -4,5 +4,5 @@
  * @ingroup rtems_disk
  *
- * Block device disk management.
+ * @brief Block device disk management implementation.
  */
  
@@ -11,4 +11,6 @@
  * Author: Victor V. Vengerov <vvv@oktet.ru>
  *
+ * Copyright (c) 2009 embedded brains GmbH.
+ *
  * @(#) $Id$
  */
@@ -18,19 +20,20 @@
 #endif
 
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
 #include <rtems.h>
 #include <rtems/libio.h>
-#include <stdlib.h>
-#include <unistd.h>	/* unlink */
-#include <string.h>
-
-#include "rtems/diskdevs.h"
-#include "rtems/bdbuf.h"
-
-#define DISKTAB_INITIAL_SIZE 32
+#include <rtems/diskdevs.h>
+#include <rtems/blkdev.h>
+#include <rtems/bdbuf.h>
+
+#define DISKTAB_INITIAL_SIZE 8
 
 /* Table of disk devices having the same major number */
 typedef struct rtems_disk_device_table {
-    rtems_disk_device **minor; /* minor-indexed disk device table */
-    uint32_t            size;            /* Number of entries in the table */
+  rtems_disk_device **minor; /* minor-indexed disk device table */
+  rtems_device_minor_number size; /* Number of entries in the table */
 } rtems_disk_device_table;
 
@@ -39,11 +42,8 @@
 
 /* Number of allocated entries in disktab table */
-static uint32_t disktab_size;
+static rtems_device_major_number disktab_size;
 
 /* Mutual exclusion semaphore for disk devices table */
 static rtems_id diskdevs_mutex;
-
-/* Flag meaning that disk I/O, buffering etc. already has been initialized. */
-static bool disk_io_initialized = false;
 
 /* diskdevs data structures protection flag.
@@ -60,161 +60,167 @@
 static volatile bool diskdevs_protected;
 
-/* create_disk_entry --
- *     Return pointer to the disk_entry structure for the specified device, or
- *     create one if it is not exists.
- *
- * PARAMETERS:
- *     dev - device id (major, minor)
- *
- * RETURNS:
- *     pointer to the disk device descriptor entry, or NULL if no memory
- *     available for its creation.
- */
-static rtems_disk_device *
-create_disk_entry(dev_t dev)
-{
-    rtems_device_major_number major;
-    rtems_device_minor_number minor;
-    rtems_disk_device **d;
-
-    rtems_filesystem_split_dev_t (dev, major, minor);
-
-    if (major >= disktab_size)
-    {
-        rtems_disk_device_table *p;
-        uint32_t newsize;
-        uint32_t i;
-        newsize = disktab_size * 2;
-        if (major >= newsize)
-            newsize = major + 1;
-        p = realloc(disktab, sizeof(rtems_disk_device_table) * newsize);
-        if (p == NULL)
-            return NULL;
-        disktab = p;
-        p += disktab_size;
-        for (i = disktab_size; i < newsize; i++, p++)
-        {
-            p->minor = NULL;
-            p->size = 0;
-        }
-        disktab_size = newsize;
-    }
-
-    if ((disktab[major].minor == NULL) ||
-        (minor >= disktab[major].size))
-    {
-        uint32_t            newsize;
-        rtems_disk_device **p;
-        uint32_t            i;
-        uint32_t            s = disktab[major].size;
-
-        if (s == 0)
-            newsize = DISKTAB_INITIAL_SIZE;
-        else
-            newsize = s * 2;
-        if (minor >= newsize)
-            newsize = minor + 1;
-
-        p = realloc(disktab[major].minor,
-                    sizeof(rtems_disk_device *) * newsize);
-        if (p == NULL)
-            return NULL;
-        disktab[major].minor = p;
-        p += s;
-        for (i = s; i < newsize; i++, p++)
-            *p = NULL;
-        disktab[major].size = newsize;
-    }
-
-    d = disktab[major].minor + minor;
-    if (*d == NULL)
-    {
-        *d = calloc(1, sizeof(rtems_disk_device));
-    }
-    return *d;
-}
-
-/* get_disk_entry --
- *     Get disk device descriptor by device number.
- *
- * PARAMETERS:
- *     dev - block device number
- *
- * RETURNS:
- *     Pointer to the disk device descriptor corresponding to the specified
- *     device number, or NULL if disk device with such number not exists.
- */
+static rtems_status_code
+disk_lock(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  sc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+  if (sc == RTEMS_SUCCESSFUL) {
+    diskdevs_protected = true;
+
+    return RTEMS_SUCCESSFUL;
+  } else {
+    return RTEMS_NOT_CONFIGURED;
+  }
+}
+
+static void
+disk_unlock(void)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  diskdevs_protected = false;
+
+  sc = rtems_semaphore_release(diskdevs_mutex);
+  if (sc != RTEMS_SUCCESSFUL) {
+    /* FIXME: Error number */
+    rtems_fatal_error_occurred(0xdeadbeef);
+  }
+}
+
 static rtems_disk_device *
 get_disk_entry(dev_t dev)
 {
-    rtems_device_major_number major;
-    rtems_device_minor_number minor;
-    rtems_disk_device_table *dtab;
-
-    rtems_filesystem_split_dev_t (dev, major, minor);
-
-    if ((major >= disktab_size) || (disktab == NULL))
-        return NULL;
-
-    dtab = disktab + major;
-
-    if ((minor >= dtab->size) || (dtab->minor == NULL))
-        return NULL;
-
-    return dtab->minor[minor];
-}
-
-/* create_disk --
- *     Check that disk entry for specified device number is not defined
- *     and create it.
- *
- * PARAMETERS:
- *     dev        - device identifier (major, minor numbers)
- *     name       - character name of device (e.g. /dev/hda)
- *     disdev     - placeholder for pointer to created disk descriptor
- *
- * RETURNS:
- *     RTEMS_SUCCESSFUL if disk entry successfully created, or
- *     error code if error occured (device already registered,
- *     no memory available).
- */
+  rtems_device_major_number major = 0;
+  rtems_device_minor_number minor = 0;
+
+  rtems_filesystem_split_dev_t(dev, major, minor);
+
+  if (major < disktab_size && disktab != NULL) {
+    rtems_disk_device_table *dtab = disktab + major;
+
+    if (minor < dtab->size && dtab->minor != NULL) {
+      rtems_disk_device *dd = dtab->minor [minor];
+
+      if (dd != NULL && !dd->deleted) {
+        ++dd->uses;
+
+        return dd;
+      }
+    }
+  }
+
+  return NULL;
+}
+
+static rtems_disk_device **
+create_disk_table_entry(dev_t dev)
+{
+  rtems_device_major_number major = 0;
+  rtems_device_minor_number minor = 0;
+
+  rtems_filesystem_split_dev_t(dev, major, minor);
+
+  if (major >= disktab_size) {
+    rtems_disk_device_table *table = disktab;
+    rtems_device_major_number old_size = disktab_size;
+    rtems_device_major_number new_size = 2 * old_size;
+
+    if (major >= new_size) {
+      new_size = major + 1;
+    }
+
+    table = realloc(table, new_size * sizeof(*table));
+    if (table == NULL) {
+      return NULL;
+    }
+
+    memset(table + old_size, 0, (new_size - old_size) * sizeof(*table));
+    disktab = table;
+    disktab_size = new_size;
+  }
+
+  if (disktab [major].minor == NULL || minor >= disktab[major].size) {
+    rtems_disk_device **table = disktab [major].minor;
+    rtems_device_minor_number old_size = disktab [major].size;
+    rtems_device_minor_number new_size = 0;
+
+    if (old_size == 0) {
+      new_size = DISKTAB_INITIAL_SIZE;
+    } else {
+      new_size = 2 * old_size;
+    }
+    if (minor >= new_size) {
+      new_size = minor + 1;
+    }
+
+    table = realloc(table, new_size * sizeof(*table));
+    if (table == NULL) {
+      return NULL;
+    }
+
+    memset(table + old_size, 0, (new_size - old_size) * sizeof(*table));
+    disktab [major].minor = table;
+    disktab [major].size = new_size;
+  }
+
+  return disktab [major].minor + minor;
+}
+
 static rtems_status_code
-create_disk(dev_t dev, const char *name, rtems_disk_device **diskdev)
-{
-    rtems_disk_device *dd;
-    char *n;
-
-    dd = get_disk_entry(dev);
-    if (dd != NULL)
-    {
-        return RTEMS_RESOURCE_IN_USE;
-    }
-
-    if (name == NULL)
-    {
-        n = NULL;
-    }
-    else
-    {
-        int nlen = strlen(name) + 1;
-        n = malloc(nlen);
-        if (n == NULL)
-            return RTEMS_NO_MEMORY;
-        strncpy(n, name, nlen);
-    }
-
-    dd = create_disk_entry(dev);
-    if (dd == NULL)
-    {
-        free(n);
-        return RTEMS_NO_MEMORY;
-    }
-
-    dd->dev = dev;
-    dd->name = n;
-
-    *diskdev = dd;
-
-    return RTEMS_SUCCESSFUL;
+create_disk(dev_t dev, const char *name, rtems_disk_device **dd_ptr)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_disk_device **dd_entry = create_disk_table_entry(dev);
+  rtems_disk_device *dd = NULL;
+  char *alloc_name = NULL;
+
+  if (dd_entry == NULL) {
+    return RTEMS_NO_MEMORY;
+  }
+
+  if (*dd_entry != NULL) {
+    return RTEMS_RESOURCE_IN_USE;
+  }
+
+  dd = malloc(sizeof(*dd));
+  if (dd == NULL) {
+    return RTEMS_NO_MEMORY;
+  }
+
+  if (name != NULL) {
+    alloc_name = strdup(name);
+    
+    if (alloc_name == NULL) {
+      free(dd);
+
+      return RTEMS_NO_MEMORY;
+    }
+  }
+
+  if (name != NULL) {
+    rtems_device_major_number major = 0;
+    rtems_device_minor_number minor = 0;
+
+    rtems_filesystem_split_dev_t(dev, major, minor);
+
+    sc = rtems_io_register_name(name, major, minor);
+    if (sc != RTEMS_SUCCESSFUL) {
+      free(alloc_name);
+      free(dd);
+
+      return RTEMS_UNSATISFIED;
+    }
+  }
+
+  dd->dev = dev;
+  dd->name = alloc_name;
+  dd->uses = 0;
+  dd->deleted = false;
+
+  *dd_entry = dd;
+  *dd_ptr = dd;
+
+  return RTEMS_SUCCESSFUL;
 }
 
@@ -222,5 +228,5 @@
   dev_t dev,
   uint32_t block_size,
-  rtems_blkdev_bnum disk_size,
+  rtems_blkdev_bnum block_count,
   rtems_block_device_ioctl handler,
   void *driver_data,
@@ -228,41 +234,47 @@
 )
 {
-    rtems_disk_device *dd;
-    rtems_status_code rc;
-    rtems_device_major_number major;
-    rtems_device_minor_number minor;
-
-    rtems_filesystem_split_dev_t (dev, major, minor);
-
-    rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-    if (rc != RTEMS_SUCCESSFUL)
-        return rc;
-    diskdevs_protected = true;
-
-    rc = create_disk(dev, name, &dd);
-    if (rc != RTEMS_SUCCESSFUL)
-    {
-        diskdevs_protected = false;
-        rtems_semaphore_release(diskdevs_mutex);
-        return rc;
-    }
-
-    dd->phys_dev = dd;
-    dd->uses = 0;
-    dd->start = 0;
-    dd->size = disk_size;
-    dd->block_size = dd->media_block_size = block_size;
-    dd->ioctl = handler;
-    dd->driver_data = driver_data;
-
-    rc = rtems_io_register_name(name, major, minor);
-
-    if (handler (dd, RTEMS_BLKDEV_CAPABILITIES, &dd->capabilities) < 0)
-      dd->capabilities = 0;
-    
-    diskdevs_protected = false;
-    rtems_semaphore_release(diskdevs_mutex);
-
-    return rc;
+  rtems_disk_device *dd = NULL;
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+  if (handler == NULL) {
+    return RTEMS_INVALID_ADDRESS;
+  }
+
+  if (block_size == 0) {
+    return RTEMS_INVALID_NUMBER;
+  }
+
+  sc = disk_lock();
+  if (sc != RTEMS_SUCCESSFUL) {
+    return sc;
+  }
+
+  sc = create_disk(dev, name, &dd);
+  if (sc != RTEMS_SUCCESSFUL) {
+    disk_unlock();
+
+    return sc;
+  }
+
+  dd->phys_dev = dd;
+  dd->start = 0;
+  dd->size = block_count;
+  dd->block_size = dd->media_block_size = block_size;
+  dd->ioctl = handler;
+  dd->driver_data = driver_data;
+
+  if ((*handler)(dd, RTEMS_BLKDEV_CAPABILITIES, &dd->capabilities) < 0) {
+    dd->capabilities = 0;
+  }
+  
+  disk_unlock();
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static bool
+is_physical_disk(const rtems_disk_device *dd)
+{
+  return dd->phys_dev == dd;
 }
 
@@ -270,94 +282,97 @@
   dev_t dev,
   dev_t phys,
-  rtems_blkdev_bnum start,
-  rtems_blkdev_bnum size,
+  rtems_blkdev_bnum begin_block,
+  rtems_blkdev_bnum block_count,
   const char *name
 )
 {
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_disk_device *physical_disk = NULL;
   rtems_disk_device *dd = NULL;
-  rtems_disk_device *pdd = NULL;
-  rtems_status_code rc = RTEMS_SUCCESSFUL;
+  rtems_blkdev_bnum end_block = begin_block + block_count;
+
+  sc = disk_lock();
+  if (sc != RTEMS_SUCCESSFUL) {
+    return sc;
+  }
+
+  physical_disk = get_disk_entry(phys);
+  if (physical_disk == NULL || !is_physical_disk(physical_disk)) {
+    if (physical_disk != NULL) {
+      --physical_disk->uses;
+    }
+    disk_unlock();
+
+    return RTEMS_INVALID_ID;
+  }
+
+  if (
+    begin_block >= physical_disk->size
+      || end_block <= begin_block
+      || end_block > physical_disk->size
+  ) {
+    --physical_disk->uses;
+    disk_unlock();
+
+    return RTEMS_INVALID_NUMBER;
+  }
+
+  sc = create_disk(dev, name, &dd);
+  if (sc != RTEMS_SUCCESSFUL) {
+    --physical_disk->uses;
+    disk_unlock();
+
+    return sc;
+  }
+
+  dd->phys_dev = physical_disk;
+  dd->start = begin_block;
+  dd->size = block_count;
+  dd->block_size = dd->media_block_size = physical_disk->block_size;
+  dd->ioctl = physical_disk->ioctl;
+  dd->driver_data = physical_disk->driver_data;
+
+  disk_unlock();
+
+  return RTEMS_SUCCESSFUL;
+}
+
+static void
+free_disk_device(rtems_disk_device *dd)
+{
+  if (is_physical_disk(dd)) {
+    (*dd->ioctl)(dd, RTEMS_BLKIO_DELETED, NULL);
+  }
+  if (dd->name != NULL) {
+    unlink(dd->name);
+    free(dd->name);
+  }
+  free(dd);
+}
+
+static void
+rtems_disk_cleanup(rtems_disk_device *disk_to_remove)
+{
+  rtems_disk_device *const physical_disk = disk_to_remove->phys_dev;
   rtems_device_major_number major = 0;
   rtems_device_minor_number minor = 0;
-  rtems_blkdev_bnum end = start + size;
-
-  rtems_filesystem_split_dev_t (dev, major, minor);
-
-  rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-  if (rc != RTEMS_SUCCESSFUL) {
-    return rc;
-  }
-
-  diskdevs_protected = true;
-
-  pdd = get_disk_entry(phys);
-  if (
-    pdd == NULL
-      || pdd != pdd->phys_dev
-      || start >= pdd->size
-      || end <= start
-      || end > pdd->size
-  ) {
-    diskdevs_protected = false;
-    rtems_semaphore_release(diskdevs_mutex);
-    return RTEMS_INVALID_NUMBER;
-  }
-
-  rc = create_disk(dev, name, &dd);
-  if (rc != RTEMS_SUCCESSFUL) {
-    diskdevs_protected = false;
-    rtems_semaphore_release(diskdevs_mutex);
-    return rc;
-  }
-
-  dd->phys_dev = pdd;
-  dd->uses = 0;
-  dd->start = start;
-  dd->size = size;
-  dd->block_size = dd->media_block_size = pdd->block_size;
-  dd->ioctl = pdd->ioctl;
-  dd->driver_data = pdd->driver_data;
-
-  rc = rtems_io_register_name(name, major, minor);
-
-  diskdevs_protected = false;
-  rc = rtems_semaphore_release(diskdevs_mutex);
-
-  return rc;
-}
-
-rtems_status_code
-rtems_disk_delete(dev_t dev)
-{
-  rtems_status_code rc = RTEMS_SUCCESSFUL;
-  rtems_device_major_number maj = 0;
-  rtems_device_minor_number min = 0;
-  rtems_disk_device *dd = NULL;
-  bool physical_disk = true;
-
-  rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-  if (rc != RTEMS_SUCCESSFUL) {
-    return rc;
-  }
-  diskdevs_protected = true;
-
-  /* Check if we have a physical or logical disk */
-  dd = get_disk_entry(dev);
-  if (dd == NULL) {
-    return RTEMS_INVALID_NUMBER;
-  }
-  physical_disk = dd->phys_dev == dd;
-
-  if (physical_disk) {
-    unsigned used = 0;
-
-    /* Check if this device is in use -- calculate usage counter */
-    for (maj = 0; maj < disktab_size; maj++) {
-      rtems_disk_device_table *dtab = disktab + maj;
-      if (dtab != NULL) {
-        for (min = 0; min < dtab->size; min++) {
-          dd = dtab->minor[min];
-          if ((dd != NULL) && (dd->phys_dev->dev == dev)) {
-            used += dd->uses;
+
+  if (physical_disk->deleted) {
+    dev_t dev = physical_disk->dev;
+    unsigned deleted_count = 0;
+
+    for (major = 0; major < disktab_size; ++major) {
+      rtems_disk_device_table *dtab = disktab + major;
+
+      for (minor = 0; minor < dtab->size; ++minor) {
+        rtems_disk_device *dd = dtab->minor [minor];
+
+        if (dd != NULL && dd->phys_dev->dev == dev && dd != physical_disk) {
+          if (dd->uses == 0) {
+            ++deleted_count;
+            dtab->minor [minor] = NULL;
+            free_disk_device(dd);
+          } else {
+            dd->deleted = true;
           }
         }
@@ -365,36 +380,45 @@
     }
 
-    if (used != 0) {
-      diskdevs_protected = false;
-      rtems_semaphore_release(diskdevs_mutex);
-      return RTEMS_RESOURCE_IN_USE;
-    }
-
-    /* Delete this device and all of its logical devices */
-    for (maj = 0; maj < disktab_size; maj++) {
-      rtems_disk_device_table *dtab = disktab + maj;
-      if (dtab != NULL) {
-        for (min = 0; min < dtab->size; min++) {
-          dd = dtab->minor[min];
-          if ((dd != NULL) && (dd->phys_dev->dev == dev)) {
-            unlink(dd->name);
-            free(dd->name);
-            free(dd);
-            dtab->minor[min] = NULL;
-          }
-        }
-      }
+    physical_disk->uses -= deleted_count;
+    if (physical_disk->uses == 0) {
+      rtems_filesystem_split_dev_t(physical_disk->dev, major, minor);
+      disktab [major].minor [minor] = NULL;
+      free_disk_device(physical_disk);
     }
   } else {
-    rtems_filesystem_split_dev_t(dev, maj, min);
-    disktab[maj].minor[min] = NULL;
-    unlink(dd->name);
-    free(dd->name);
-    free(dd);
-  }
-
-  diskdevs_protected = false;
-  rc = rtems_semaphore_release(diskdevs_mutex);
-  return rc;
+    if (disk_to_remove->uses == 0) {
+      --physical_disk->uses;
+      rtems_filesystem_split_dev_t(disk_to_remove->dev, major, minor);
+      disktab [major].minor [minor] = NULL;
+      free_disk_device(disk_to_remove);
+    }
+  }
+}
+
+rtems_status_code
+rtems_disk_delete(dev_t dev)
+{
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_disk_device *dd = NULL;
+
+  sc = disk_lock();
+  if (sc != RTEMS_SUCCESSFUL) {
+    return sc;
+  }
+
+  dd = get_disk_entry(dev);
+  if (dd == NULL) {
+    disk_unlock();
+
+    return RTEMS_INVALID_ID;
+  }
+
+  --dd->uses;
+  dd->deleted = true;
+  rtems_disk_cleanup(dd);
+
+  disk_unlock();
+
+  return RTEMS_SUCCESSFUL;
 }
 
@@ -402,31 +426,24 @@
 rtems_disk_obtain(dev_t dev)
 {
-    rtems_interrupt_level level;
-    rtems_disk_device *dd;
-    rtems_status_code rc;
-
-    rtems_interrupt_disable(level);
-    if (diskdevs_protected)
-    {
-        rtems_interrupt_enable(level);
-        rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT,
-                                    RTEMS_NO_TIMEOUT);
-        if (rc != RTEMS_SUCCESSFUL)
-            return NULL;
-        diskdevs_protected = true;
-        dd = get_disk_entry(dev);
-        dd->uses++;
-        diskdevs_protected = false;
-        rtems_semaphore_release(diskdevs_mutex);
-        return dd;
-    }
-    else
-    {
-        /* Frequent and quickest case */
-        dd = get_disk_entry(dev);
-        dd->uses++;
-        rtems_interrupt_enable(level);
-        return dd;
-    }
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_disk_device *dd = NULL;
+  rtems_interrupt_level level;
+
+  rtems_interrupt_disable(level);
+  if (!diskdevs_protected) {
+    /* Frequent and quickest case */
+    dd = get_disk_entry(dev);
+    rtems_interrupt_enable(level);
+  } else {
+    rtems_interrupt_enable(level);
+
+    sc = disk_lock();
+    if (sc == RTEMS_SUCCESSFUL) {
+      dd = get_disk_entry(dev);
+      disk_unlock();
+    }
+  }
+
+  return dd;
 }
 
@@ -434,9 +451,19 @@
 rtems_disk_release(rtems_disk_device *dd)
 {
-    rtems_interrupt_level level;
-    rtems_interrupt_disable(level);
-    dd->uses--;
-    rtems_interrupt_enable(level);
-    return RTEMS_SUCCESSFUL;
+  rtems_interrupt_level level;
+  dev_t dev = dd->dev;
+  unsigned uses = 0;
+  bool deleted = false;
+
+  rtems_interrupt_disable(level);
+  uses = --dd->uses;
+  deleted = dd->deleted;
+  rtems_interrupt_enable(level);
+
+  if (uses == 0 && deleted) {
+    rtems_disk_delete(dev);
+  }
+
+  return RTEMS_SUCCESSFUL;
 }
 
@@ -476,37 +503,42 @@
 rtems_disk_io_initialize(void)
 {
-    rtems_status_code rc;
-
-    if (disk_io_initialized)
-        return RTEMS_SUCCESSFUL;
-
-    disktab_size = DISKTAB_INITIAL_SIZE;
-    disktab = calloc(disktab_size, sizeof(rtems_disk_device_table));
-    if (disktab == NULL)
-        return RTEMS_NO_MEMORY;
-
-    diskdevs_protected = false;
-    rc = rtems_semaphore_create(
-        rtems_build_name('D', 'D', 'E', 'V'), 1,
-        RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
-        RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0, &diskdevs_mutex);
-
-    if (rc != RTEMS_SUCCESSFUL)
-    {
-        free(disktab);
-        return rc;
-    }
-
-    rc = rtems_bdbuf_init();
-
-    if (rc != RTEMS_SUCCESSFUL)
-    {
-        rtems_semaphore_delete(diskdevs_mutex);
-        free(disktab);
-        return rc;
-    }
-
-    disk_io_initialized = 1;
+  rtems_status_code sc = RTEMS_SUCCESSFUL;
+  rtems_device_major_number size = DISKTAB_INITIAL_SIZE;
+
+  if (disktab_size > 0) {
     return RTEMS_SUCCESSFUL;
+  }
+
+  disktab = calloc(size, sizeof(rtems_disk_device_table));
+  if (disktab == NULL) {
+    return RTEMS_NO_MEMORY;
+  }
+
+  diskdevs_protected = false;
+  sc = rtems_semaphore_create(
+    rtems_build_name('D', 'D', 'E', 'V'),
+    1,
+    RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY
+      | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
+    0,
+    &diskdevs_mutex
+  );
+  if (sc != RTEMS_SUCCESSFUL) {
+    free(disktab);
+
+    return RTEMS_NO_MEMORY;
+  }
+
+  sc = rtems_bdbuf_init();
+  if (sc != RTEMS_SUCCESSFUL) {
+    rtems_semaphore_delete(diskdevs_mutex);
+    free(disktab);
+
+    return RTEMS_UNSATISFIED;
+  }
+
+  disktab_size = size;
+
+  return RTEMS_SUCCESSFUL;
 }
 
@@ -514,29 +546,27 @@
 rtems_disk_io_done(void)
 {
-    rtems_device_major_number maj;
-    rtems_device_minor_number min;
-    rtems_status_code rc;
-
-    /* Free data structures */
-    for (maj = 0; maj < disktab_size; maj++)
-    {
-        rtems_disk_device_table *dtab = disktab + maj;
-        if (dtab != NULL)
-        {
-            for (min = 0; min < dtab->size; min++)
-            {
-                rtems_disk_device *dd = dtab->minor[min];
-                unlink(dd->name);
-                free(dd->name);
-                free(dd);
-            }
-            free(dtab);
-        }
-    }
-    free(disktab);
-
-    rc = rtems_semaphore_delete(diskdevs_mutex);
-
-    disk_io_initialized = 0;
-    return rc;
-}
+  rtems_device_major_number major = 0;
+  rtems_device_minor_number minor = 0;
+
+  for (major = 0; major < disktab_size; ++major) {
+    rtems_disk_device_table *dtab = disktab + major;
+
+    for (minor = 0; minor < dtab->size; ++minor) {
+      rtems_disk_device *dd = dtab->minor [minor];
+
+      if (dd != NULL) {
+        free_disk_device(dd);
+      }
+    }
+    free(dtab->minor);
+  }
+  free(disktab);
+
+  rtems_semaphore_delete(diskdevs_mutex);
+
+  diskdevs_mutex = RTEMS_ID_NONE;
+  disktab = NULL;
+  disktab_size = 0;
+
+  return RTEMS_SUCCESSFUL;
+}
Index: cpukit/libblock/src/ramdisk-driver.c
===================================================================
--- cpukit/libblock/src/ramdisk-driver.c	(revision 1560d12d0141710c3aa63f3409ce0d0b4a41dc30)
+++ cpukit/libblock/src/ramdisk-driver.c	(revision d61f0a7ba5f9569fea05ce2624c53b8466600e88)
@@ -14,25 +14,34 @@
  */
 
-#include <stdio.h>
+/* FIXME: How to set this define? */
+#if !defined(RTEMS_RAMDISK_TRACE)
+    #define RTEMS_RAMDISK_TRACE 0
+#endif
+
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
-#include <inttypes.h>
+
+#if RTEMS_RAMDISK_TRACE
+    #include <stdio.h>
+#endif
 
 #include <rtems.h>
 #include <rtems/ramdisk.h>
 
-static void
-rtems_ramdisk_printf (const ramdisk *rd, const char *format, ...)
-{
-  if (rd->trace)
-  {
-    va_list args;
-    va_start (args, format);
-    printf ("ramdisk:");
-    vprintf (format, args);
-    printf ("\n");
-  }
-}
+#if RTEMS_RAMDISK_TRACE
+    static void
+    rtems_ramdisk_printf (const ramdisk *rd, const char *format, ...)
+    {
+        if (rd->trace)
+        {
+            va_list args;
+            va_start (args, format);
+            printf ("ramdisk:");
+            vprintf (format, args);
+            printf ("\n");
+        }
+    }
+#endif
 
 static int
@@ -43,12 +52,16 @@
     rtems_blkdev_sg_buffer *sg;
 
+#if RTEMS_RAMDISK_TRACE
     rtems_ramdisk_printf (rd, "ramdisk read: start=%d, blocks=%d",
                           req->bufs[0].block, req->bufnum);
+#endif
 
     for (i = 0, sg = req->bufs; i < req->bufnum; i++, sg++)
     {
+#if RTEMS_RAMDISK_TRACE
         rtems_ramdisk_printf (rd, "ramdisk read: buf=%d block=%d length=%d off=%d addr=%p",
                               i, sg->block, sg->length, sg->block * rd->block_size,
                               from + (sg->block * rd->block_size));
+#endif
         memcpy(sg->buffer, from + (sg->block * rd->block_size), sg->length);
     }
@@ -64,11 +77,15 @@
     rtems_blkdev_sg_buffer *sg;
 
+#if RTEMS_RAMDISK_TRACE
     rtems_ramdisk_printf (rd, "ramdisk write: start=%d, blocks=%d",
                           req->bufs[0].block, req->bufnum);
+#endif
     for (i = 0, sg = req->bufs; i < req->bufnum; i++, sg++)
     {
+#if RTEMS_RAMDISK_TRACE
         rtems_ramdisk_printf (rd, "ramdisk write: buf=%d block=%d length=%d off=%d addr=%p",
                               i, sg->block, sg->length, sg->block * rd->block_size,
                               to + (sg->block * rd->block_size));
+#endif
         memcpy(to + (sg->block * rd->block_size), sg->buffer, sg->length);
     }
