diff options
-rw-r--r-- | cpukit/ChangeLog | 17 | ||||
-rw-r--r-- | cpukit/libblock/include/rtems/blkdev.h | 1 | ||||
-rw-r--r-- | cpukit/libblock/include/rtems/diskdevs.h | 120 | ||||
-rw-r--r-- | cpukit/libblock/include/rtems/ramdisk.h | 10 | ||||
-rw-r--r-- | cpukit/libblock/src/diskdevs.c | 718 | ||||
-rw-r--r-- | cpukit/libblock/src/ramdisk-driver.c | 45 |
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); |