summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/ChangeLog17
-rw-r--r--cpukit/libblock/include/rtems/blkdev.h1
-rw-r--r--cpukit/libblock/include/rtems/diskdevs.h120
-rw-r--r--cpukit/libblock/include/rtems/ramdisk.h10
-rw-r--r--cpukit/libblock/src/diskdevs.c718
-rw-r--r--cpukit/libblock/src/ramdisk-driver.c45
6 files changed, 513 insertions, 398 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index fd2366548f..c62ef53ca1 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,3 +1,8 @@
+2009-10-20 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libblock/include/rtems/ramdisk.h: Documentation.
+ * libblock/src/ramdisk-driver.c: Compile trace support conditionally.
+
2009-10-20 Chris Johns <chrisj@rtems.org>
* libnetworking/rtems/rtems_mii_ioctl_kern.c: Added IFM_ACTIVE and
@@ -5,6 +10,18 @@
but in the BSD stack. Before IFM_LINK_OK was set and this is a
spare bit.
+2009-10-19 Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+ * libblock/include/rtems/diskdevs.h: Documentation. Added field to
+ rtems_disk_device.
+ * libblock/include/rtems/blkdev.h: New request code
+ RTEMS_BLKIO_DELETED.
+ * libblock/src/diskdevs.c: Major rewrite. Changed the way disks are
+ deleted. Disks will be now deleted if they are not in use or upon
+ last release. The IO control handler will be invoked if a physical
+ disk is deleted with the RTEMS_BLKIO_DELETED request code. Logical
+ disks increase now the usage count of the associated physical disk.
+
2009-10-16 Sebastian Huber <sebastian.huber@embedded-brains.de>
* libblock/src/ramdisk.c: Removed file.
diff --git a/cpukit/libblock/include/rtems/blkdev.h b/cpukit/libblock/include/rtems/blkdev.h
index 3dec8ead03..721ecbb707 100644
--- a/cpukit/libblock/include/rtems/blkdev.h
+++ b/cpukit/libblock/include/rtems/blkdev.h
@@ -162,6 +162,7 @@ typedef struct rtems_blkdev_request {
#define RTEMS_BLKIO_SETBLKSIZE _IO('B', 4)
#define RTEMS_BLKIO_GETSIZE _IO('B', 5)
#define RTEMS_BLKIO_SYNCDEV _IO('B', 6)
+#define RTEMS_BLKIO_DELETED _IO('B', 7)
/** @} */
diff --git a/cpukit/libblock/include/rtems/diskdevs.h b/cpukit/libblock/include/rtems/diskdevs.h
index 0f0755fbb1..025bfb46f4 100644
--- a/cpukit/libblock/include/rtems/diskdevs.h
+++ b/cpukit/libblock/include/rtems/diskdevs.h
@@ -3,7 +3,7 @@
*
* @ingroup rtems_disk
*
- * Block device disk management.
+ * @brief Block device disk management API.
*/
/*
@@ -89,7 +89,7 @@ struct rtems_disk_device {
/**
* @brief Usage counter.
*
- * Devices cannot be removed if they are in use.
+ * Devices cannot be deleted if they are in use.
*/
unsigned uses;
@@ -129,6 +129,12 @@ struct rtems_disk_device {
* @brief Private data for the disk driver.
*/
void *driver_data;
+
+ /**
+ * @brief Indicates that this disk should be deleted as soon as the last user
+ * releases this disk.
+ */
+ bool deleted;
};
/**
@@ -203,19 +209,27 @@ static inline uint32_t rtems_disk_media_block_size(const rtems_disk_device *dd)
/**
* @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,
const char *name
@@ -226,27 +240,44 @@ rtems_status_code rtems_disk_create_phys(
*
* 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
);
/**
* @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);
@@ -254,15 +285,19 @@ rtems_status_code rtems_disk_delete(dev_t dev);
* @brief Returns the disk device descriptor for the device identifier @a dev.
*
* 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.
*/
rtems_disk_device *rtems_disk_obtain(dev_t dev);
/**
- * @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);
@@ -275,32 +310,24 @@ rtems_status_code rtems_disk_release(rtems_disk_device *dd);
*/
/**
- * @brief Disk device iterator.
- *
- * Returns the next disk device descriptor with a device identifier larger than
- * @a dev. If there is no such device, @c NULL will be returned. Use minus
- * one to start the search.
- *
- * @code
- * rtems_disk_device *dd = rtems_disk_next((dev_t) -1);
- *
- * while (dd != NULL) {
- * dd = rtems_disk_next(dd->dev);
- * }
- * @endcode
- */
-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.
+ *
+ * @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);
@@ -308,6 +335,23 @@ rtems_status_code rtems_disk_io_done(void);
/** @} */
+/**
+ * @brief Disk device iterator.
+ *
+ * Returns the next disk device descriptor with a device identifier larger than
+ * @a dev. If there is no such device, @c NULL will be returned. Use minus
+ * one to start the search.
+ *
+ * @code
+ * rtems_disk_device *dd = rtems_disk_next((dev_t) -1);
+ *
+ * while (dd != NULL) {
+ * dd = rtems_disk_next(dd->dev);
+ * }
+ * @endcode
+ */
+rtems_disk_device *rtems_disk_next(dev_t dev);
+
#ifdef __cplusplus
}
#endif
diff --git a/cpukit/libblock/include/rtems/ramdisk.h b/cpukit/libblock/include/rtems/ramdisk.h
index e1c6a17355..fc40816f54 100644
--- a/cpukit/libblock/include/rtems/ramdisk.h
+++ b/cpukit/libblock/include/rtems/ramdisk.h
@@ -75,8 +75,6 @@ extern rtems_ramdisk_config rtems_ramdisk_configuration [];
*/
extern size_t rtems_ramdisk_configuration_size;
-int ramdisk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
-
/**
* @brief RAM disk driver initialization entry point.
*/
@@ -142,6 +140,8 @@ typedef struct ramdisk {
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.
*
@@ -153,7 +153,13 @@ extern const rtems_driver_address_table ramdisk_ops;
* @return Pointer to allocated and initialized ramdisk structure, or @c NULL
* 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,
* uint32_t block_size,
diff --git a/cpukit/libblock/src/diskdevs.c b/cpukit/libblock/src/diskdevs.c
index 8655e77758..5256c84bf8 100644
--- a/cpukit/libblock/src/diskdevs.c
+++ b/cpukit/libblock/src/diskdevs.c
@@ -3,13 +3,15 @@
*
* @ingroup rtems_disk
*
- * Block device disk management.
+ * @brief Block device disk management implementation.
*/
/*
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Victor V. Vengerov <vvv@oktet.ru>
*
+ * Copyright (c) 2009 embedded brains GmbH.
+ *
* @(#) $Id$
*/
@@ -17,35 +19,33 @@
#include "config.h"
#endif
-#include <rtems.h>
-#include <rtems/libio.h>
#include <stdlib.h>
-#include <unistd.h> /* unlink */
+#include <unistd.h>
#include <string.h>
-#include "rtems/diskdevs.h"
-#include "rtems/bdbuf.h"
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/diskdevs.h>
+#include <rtems/blkdev.h>
+#include <rtems/bdbuf.h>
-#define DISKTAB_INITIAL_SIZE 32
+#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;
/* Pointer to [major].minor[minor] indexed array of disk devices */
static rtems_disk_device_table *disktab;
/* 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.
* Normally, only table lookup operations performed. It is quite fast, so
* it is possible to done lookups when interrupts are disabled, avoiding
@@ -59,385 +59,412 @@ static bool disk_io_initialized = false;
*/
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)
+static rtems_status_code
+disk_lock(void)
{
- rtems_device_major_number major;
- rtems_device_minor_number minor;
- rtems_disk_device **d;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
- rtems_filesystem_split_dev_t (dev, major, minor);
+ sc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc == RTEMS_SUCCESSFUL) {
+ diskdevs_protected = true;
- 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;
- }
+ return RTEMS_SUCCESSFUL;
+ } else {
+ return RTEMS_NOT_CONFIGURED;
+ }
+}
- 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;
+static void
+disk_unlock(void)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
- 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;
- }
+ diskdevs_protected = false;
- d = disktab[major].minor + minor;
- if (*d == NULL)
- {
- *d = calloc(1, sizeof(rtems_disk_device));
- }
- return *d;
+ sc = rtems_semaphore_release(diskdevs_mutex);
+ if (sc != RTEMS_SUCCESSFUL) {
+ /* FIXME: Error number */
+ rtems_fatal_error_occurred(0xdeadbeef);
+ }
}
-/* 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_disk_device *
get_disk_entry(dev_t dev)
{
- rtems_device_major_number major;
- rtems_device_minor_number minor;
- rtems_disk_device_table *dtab;
+ rtems_device_major_number major = 0;
+ rtems_device_minor_number minor = 0;
- rtems_filesystem_split_dev_t (dev, major, minor);
+ rtems_filesystem_split_dev_t(dev, major, minor);
- if ((major >= disktab_size) || (disktab == NULL))
- return NULL;
+ if (major < disktab_size && disktab != NULL) {
+ rtems_disk_device_table *dtab = disktab + major;
- dtab = disktab + major;
+ if (minor < dtab->size && dtab->minor != NULL) {
+ rtems_disk_device *dd = dtab->minor [minor];
- if ((minor >= dtab->size) || (dtab->minor == NULL))
- return NULL;
+ if (dd != NULL && !dd->deleted) {
+ ++dd->uses;
- return dtab->minor[minor];
+ return dd;
+ }
+ }
+ }
+
+ return NULL;
}
-/* 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).
- */
-static rtems_status_code
-create_disk(dev_t dev, const char *name, rtems_disk_device **diskdev)
+static rtems_disk_device **
+create_disk_table_entry(dev_t dev)
{
- rtems_disk_device *dd;
- char *n;
+ rtems_device_major_number major = 0;
+ rtems_device_minor_number minor = 0;
- dd = get_disk_entry(dev);
- if (dd != NULL)
- {
- return RTEMS_RESOURCE_IN_USE;
+ 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;
}
- if (name == NULL)
- {
- n = NULL;
+ table = realloc(table, new_size * sizeof(*table));
+ if (table == NULL) {
+ return NULL;
}
- else
- {
- int nlen = strlen(name) + 1;
- n = malloc(nlen);
- if (n == NULL)
- return RTEMS_NO_MEMORY;
- strncpy(n, name, nlen);
+
+ 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;
}
- dd = create_disk_entry(dev);
- if (dd == NULL)
- {
- free(n);
- return RTEMS_NO_MEMORY;
+ table = realloc(table, new_size * sizeof(*table));
+ if (table == NULL) {
+ return NULL;
}
- dd->dev = dev;
- dd->name = n;
+ memset(table + old_size, 0, (new_size - old_size) * sizeof(*table));
+ disktab [major].minor = table;
+ disktab [major].size = new_size;
+ }
- *diskdev = dd;
+ return disktab [major].minor + minor;
+}
- return RTEMS_SUCCESSFUL;
+static rtems_status_code
+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;
}
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,
const char *name
)
{
- rtems_disk_device *dd;
- rtems_status_code rc;
- rtems_device_major_number major;
- rtems_device_minor_number minor;
+ rtems_disk_device *dd = NULL;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
- rtems_filesystem_split_dev_t (dev, major, minor);
+ if (handler == NULL) {
+ return RTEMS_INVALID_ADDRESS;
+ }
- rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (rc != RTEMS_SUCCESSFUL)
- return rc;
- diskdevs_protected = true;
+ if (block_size == 0) {
+ return RTEMS_INVALID_NUMBER;
+ }
- rc = create_disk(dev, name, &dd);
- if (rc != RTEMS_SUCCESSFUL)
- {
- diskdevs_protected = false;
- rtems_semaphore_release(diskdevs_mutex);
- return rc;
- }
+ sc = disk_lock();
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
+ }
- 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;
+ sc = create_disk(dev, name, &dd);
+ if (sc != RTEMS_SUCCESSFUL) {
+ disk_unlock();
- rc = rtems_io_register_name(name, major, minor);
+ return sc;
+ }
- if (handler (dd, RTEMS_BLKDEV_CAPABILITIES, &dd->capabilities) < 0)
- dd->capabilities = 0;
-
- diskdevs_protected = false;
- rtems_semaphore_release(diskdevs_mutex);
+ 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 rc;
+ return RTEMS_SUCCESSFUL;
+}
+
+static bool
+is_physical_disk(const rtems_disk_device *dd)
+{
+ return dd->phys_dev == dd;
}
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
)
{
+ 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_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);
+ rtems_blkdev_bnum end_block = begin_block + block_count;
- rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
- if (rc != RTEMS_SUCCESSFUL) {
- return rc;
+ sc = disk_lock();
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
}
- diskdevs_protected = true;
+ 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;
+ }
- pdd = get_disk_entry(phys);
if (
- pdd == NULL
- || pdd != pdd->phys_dev
- || start >= pdd->size
- || end <= start
- || end > pdd->size
+ begin_block >= physical_disk->size
+ || end_block <= begin_block
+ || end_block > physical_disk->size
) {
- diskdevs_protected = false;
- rtems_semaphore_release(diskdevs_mutex);
+ --physical_disk->uses;
+ disk_unlock();
+
return RTEMS_INVALID_NUMBER;
}
- rc = create_disk(dev, name, &dd);
- if (rc != RTEMS_SUCCESSFUL) {
- diskdevs_protected = false;
- rtems_semaphore_release(diskdevs_mutex);
- return rc;
+ sc = create_disk(dev, name, &dd);
+ if (sc != RTEMS_SUCCESSFUL) {
+ --physical_disk->uses;
+ disk_unlock();
+
+ return sc;
}
- 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;
+ 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;
- rc = rtems_io_register_name(name, major, minor);
+ disk_unlock();
- diskdevs_protected = false;
- rc = rtems_semaphore_release(diskdevs_mutex);
+ return RTEMS_SUCCESSFUL;
+}
- return rc;
+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;
+
+ 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;
+ }
+ }
+ }
+ }
+
+ 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 {
+ 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 rc = RTEMS_SUCCESSFUL;
- rtems_device_major_number maj = 0;
- rtems_device_minor_number min = 0;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
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;
+ sc = disk_lock();
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
}
- diskdevs_protected = true;
- /* Check if we have a physical or logical disk */
dd = get_disk_entry(dev);
if (dd == NULL) {
- return RTEMS_INVALID_NUMBER;
+ disk_unlock();
+
+ return RTEMS_INVALID_ID;
}
- 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 (used != 0) {
- diskdevs_protected = false;
- rtems_semaphore_release(diskdevs_mutex);
- return RTEMS_RESOURCE_IN_USE;
- }
+ --dd->uses;
+ dd->deleted = true;
+ rtems_disk_cleanup(dd);
- /* 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;
- }
- }
- }
- }
- } else {
- rtems_filesystem_split_dev_t(dev, maj, min);
- disktab[maj].minor[min] = NULL;
- unlink(dd->name);
- free(dd->name);
- free(dd);
- }
+ disk_unlock();
- diskdevs_protected = false;
- rc = rtems_semaphore_release(diskdevs_mutex);
- return rc;
+ return RTEMS_SUCCESSFUL;
}
rtems_disk_device *
rtems_disk_obtain(dev_t dev)
{
- rtems_interrupt_level level;
- rtems_disk_device *dd;
- rtems_status_code rc;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_disk_device *dd = NULL;
+ rtems_interrupt_level level;
- 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_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;
}
rtems_status_code
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;
}
rtems_disk_device *
@@ -475,68 +502,71 @@ rtems_disk_next(dev_t dev)
rtems_status_code
rtems_disk_io_initialize(void)
{
- rtems_status_code rc;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_device_major_number size = DISKTAB_INITIAL_SIZE;
- if (disk_io_initialized)
- return RTEMS_SUCCESSFUL;
+ if (disktab_size > 0) {
+ return RTEMS_SUCCESSFUL;
+ }
- disktab_size = DISKTAB_INITIAL_SIZE;
- disktab = calloc(disktab_size, sizeof(rtems_disk_device_table));
- if (disktab == NULL)
- return RTEMS_NO_MEMORY;
+ disktab = calloc(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);
+ 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);
- if (rc != RTEMS_SUCCESSFUL)
- {
- free(disktab);
- return rc;
- }
+ return RTEMS_NO_MEMORY;
+ }
- rc = rtems_bdbuf_init();
+ sc = rtems_bdbuf_init();
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_semaphore_delete(diskdevs_mutex);
+ free(disktab);
- if (rc != RTEMS_SUCCESSFUL)
- {
- rtems_semaphore_delete(diskdevs_mutex);
- free(disktab);
- return rc;
- }
+ return RTEMS_UNSATISFIED;
+ }
- disk_io_initialized = 1;
- return RTEMS_SUCCESSFUL;
+ disktab_size = size;
+
+ return RTEMS_SUCCESSFUL;
}
rtems_status_code
rtems_disk_io_done(void)
{
- rtems_device_major_number maj;
- rtems_device_minor_number min;
- rtems_status_code rc;
+ rtems_device_major_number major = 0;
+ rtems_device_minor_number minor = 0;
- /* 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);
- }
+ 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(disktab);
+ free(dtab->minor);
+ }
+ free(disktab);
+
+ rtems_semaphore_delete(diskdevs_mutex);
- rc = rtems_semaphore_delete(diskdevs_mutex);
+ diskdevs_mutex = RTEMS_ID_NONE;
+ disktab = NULL;
+ disktab_size = 0;
- disk_io_initialized = 0;
- return rc;
+ return RTEMS_SUCCESSFUL;
}
diff --git a/cpukit/libblock/src/ramdisk-driver.c b/cpukit/libblock/src/ramdisk-driver.c
index 42e2a6a424..80503c9f3c 100644
--- a/cpukit/libblock/src/ramdisk-driver.c
+++ b/cpukit/libblock/src/ramdisk-driver.c
@@ -13,27 +13,36 @@
* @(#) $Id$
*/
-#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
ramdisk_read(struct ramdisk *rd, rtems_blkdev_request *req)
@@ -42,14 +51,18 @@ ramdisk_read(struct ramdisk *rd, rtems_blkdev_request *req)
uint32_t i;
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);
}
req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);
@@ -63,13 +76,17 @@ ramdisk_write(struct ramdisk *rd, rtems_blkdev_request *req)
uint32_t i;
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);
}
req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);