summaryrefslogtreecommitdiffstats
path: root/cpukit/libblock
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2009-10-20 07:53:19 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2009-10-20 07:53:19 +0000
commite41369ef8cf419e3e9f5c3816f05c383a5f076f5 (patch)
tree709ed1a6ded82913d94ce062d30198790c2a7454 /cpukit/libblock
parent2009-10-20 Ralf Corsépius <ralf.corsepius@rtems.org> (diff)
downloadrtems-e41369ef8cf419e3e9f5c3816f05c383a5f076f5.tar.bz2
* 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. * libblock/include/rtems/ramdisk.h: Documentation. * libblock/src/ramdisk-driver.c: Compile trace support conditionally.
Diffstat (limited to 'cpukit/libblock')
-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
5 files changed, 496 insertions, 398 deletions
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);