Changeset e41369ef in rtems for cpukit/libblock


Ignore:
Timestamp:
10/20/09 07:53:19 (14 years ago)
Author:
Thomas Doerfler <Thomas.Doerfler@…>
Branches:
4.10, 4.11, 5, master
Children:
d61f0a7b
Parents:
b83c7ba9
Message:
  • 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.
Location:
cpukit/libblock
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libblock/include/rtems/blkdev.h

    rb83c7ba9 re41369ef  
    163163#define RTEMS_BLKIO_GETSIZE         _IO('B', 5)
    164164#define RTEMS_BLKIO_SYNCDEV         _IO('B', 6)
     165#define RTEMS_BLKIO_DELETED         _IO('B', 7)
    165166
    166167/** @} */
  • cpukit/libblock/include/rtems/diskdevs.h

    rb83c7ba9 re41369ef  
    44 * @ingroup rtems_disk
    55 *
    6  * Block device disk management.
     6 * @brief Block device disk management API.
    77 */
    88 
     
    9090   * @brief Usage counter.
    9191   *
    92    * Devices cannot be removed if they are in use.
     92   * Devices cannot be deleted if they are in use.
    9393   */
    9494  unsigned uses;
     
    130130   */
    131131  void *driver_data;
     132
     133  /**
     134   * @brief Indicates that this disk should be deleted as soon as the last user
     135   * releases this disk.
     136   */
     137  bool deleted;
    132138};
    133139
     
    204210 * @brief Creates a physical disk with device identifier @a dev.
    205211 *
    206  * The block size @a block_size must be a power of two.  The disk size @a
    207  * disk_size is the number of blocks provided by this disk.  The block index
    208  * starts with zero.  The associated disk device driver will be invoked via the
    209  * IO control handler @a handler.  A device node will be registered in the file
    210  * system with absolute path @a name.  This function is usually invoked from a
     212 * The block size @a block_size must be positive.  The disk will have
     213 * @a block_count blocks.  The block index starts with zero.  The associated disk
     214 * device driver will be invoked via the IO control handler @a handler.  A
     215 * device node will be registered in the file system with absolute path @a
     216 * name, if @a name is not @c NULL.  This function is usually invoked from a
    211217 * block device driver during initialization when a physical device is detected
    212218 * in the system.  The device driver provides an IO control handler to allow
    213219 * block device operations.
     220 *
     221 * @retval RTEMS_SUCCESSFUL Successful operation.
     222 * @retval RTEMS_NOT_CONFIGURED Cannot lock disk device operation mutex.
     223 * @retval RTEMS_INVALID_ADDRESS IO control handler is @c NULL.
     224 * @retval RTEMS_INVALID_NUMBER Block size is zero.
     225 * @retval RTEMS_NO_MEMORY Not enough memory.
     226 * @retval RTEMS_RESOURCE_IN_USE Disk device descriptor is already in use.
     227 * @retval RTEMS_UNSATISFIED Cannot create device node.
    214228 */
    215229rtems_status_code rtems_disk_create_phys(
    216230  dev_t dev,
    217231  uint32_t block_size,
    218   rtems_blkdev_bnum disk_size,
     232  rtems_blkdev_bnum block_count,
    219233  rtems_block_device_ioctl handler,
    220234  void *driver_data,
     
    227241 * A logical disk manages a subset of consecutive blocks contained in the
    228242 * physical disk with identifier @a phys.  The start block index of the logical
    229  * disk device is @a start.  The block number of the logcal disk will be @a
    230  * size.  The blocks must be within the range of blocks managed by the
    231  * associated physical disk device.  A device node will be registered in the
    232  * file system with absolute path @a name.  The block size and IO control
    233  * handler are inherited by the physical disk.
     243 * disk device is @a begin_block.  The block count of the logcal disk will be
     244 * @a block_count.  The blocks must be within the range of blocks managed by
     245 * the associated physical disk device.  A device node will be registered in
     246 * the file system with absolute path @a name, if @a name is not @c NULL.  The
     247 * block size and IO control handler are inherited by the physical disk.
     248 *
     249 * @retval RTEMS_SUCCESSFUL Successful operation.
     250 * @retval RTEMS_NOT_CONFIGURED Cannot lock disk device operation mutex.
     251 * @retval RTEMS_INVALID_ID Specified physical disk identifier does not
     252 * correspond to a physical disk.
     253 * @retval RTEMS_INVALID_NUMBER Begin block or block count are out of range.
     254 * @retval RTEMS_NO_MEMORY Not enough memory.
     255 * @retval RTEMS_RESOURCE_IN_USE Disk device descriptor for logical disk
     256 * identifier is already in use.
     257 * @retval RTEMS_UNSATISFIED Cannot create device node.
    234258 */
    235259rtems_status_code rtems_disk_create_log(
    236260  dev_t dev,
    237261  dev_t phys,
    238   rtems_blkdev_bnum start,
    239   rtems_blkdev_bnum size,
     262  rtems_blkdev_bnum begin_block,
     263  rtems_blkdev_bnum block_count,
    240264  const char *name
    241265);
     
    244268 * @brief Deletes a physical or logical disk device with identifier @a dev.
    245269 *
    246  * Disk devices may be deleted if there usage counter (and the usage counters
    247  * of all contained logical disks devices) equals zero.  When a physical disk
    248  * device is deleted, all logical disk devices will deleted too.  The
    249  * corresponding device nodes will be removed from the file system.
     270 * Marks the disk device as deleted.  When a physical disk device is deleted,
     271 * all corresponding logical disk devices will marked as deleted too.  Disks
     272 * that are marked as deleted and have a usage counter of zero will be deleted.
     273 * The corresponding device nodes will be removed from the file system.  In
     274 * case of a physical disk deletion the IO control handler will be invoked with
     275 * a RTEMS_BLKIO_DELETED request.  Disks that are still in use will be deleted
     276 * upon release.
     277 *
     278 * @retval RTEMS_SUCCESSFUL Successful operation.
     279 * @retval RTEMS_NOT_CONFIGURED Cannot lock disk device operation mutex.
     280 * @retval RTEMS_INVALID_ID No disk for specified device identifier.
    250281 */
    251282rtems_status_code rtems_disk_delete(dev_t dev);
     
    255286 *
    256287 * Increments usage counter by one.  You should release the disk device
    257  * descriptor with rtems_disk_release().  Returns @c NULL if no corresponding
     288 * descriptor with rtems_disk_release().
     289 *
     290 * @return Pointer to the disk device descriptor or @c NULL if no corresponding
    258291 * disk exists.
    259292 */
     
    261294
    262295/**
    263  * @brief Releases the disk device description @a dd.
     296 * @brief Releases the disk device descriptor @a dd.
    264297 *
    265298 * Decrements usage counter by one.
     299 *
     300 * @retval RTEMS_SUCCESSFUL Successful operation.
    266301 */
    267302rtems_status_code rtems_disk_release(rtems_disk_device *dd);
     
    274309 * @{
    275310 */
     311
     312/**
     313 * @brief Initializes the disk device management.
     314 *
     315 * This functions returns successful if the disk device management is already
     316 * initialized.  There is no protection against concurrent access.
     317 *
     318 * @retval RTEMS_SUCCESSFUL Successful initialization.
     319 * @retval RTEMS_NO_MEMORY Not enough memory or no semaphore available.
     320 * @retval RTEMS_UNSATISFIED Block device buffer initialization failed.
     321 */
     322rtems_status_code rtems_disk_io_initialize(void);
     323
     324/**
     325 * @brief Releases all resources allocated for disk device management.
     326 *
     327 * There is no protection against concurrent access.  If parts of the system
     328 * are still in use the behaviour is undefined.
     329 *
     330 * @retval RTEMS_SUCCESSFUL Successful operation.
     331 */
     332rtems_status_code rtems_disk_io_done(void);
     333
     334/** @} */
     335
     336/** @} */
    276337
    277338/**
     
    292353rtems_disk_device *rtems_disk_next(dev_t dev);
    293354
    294 /**
    295  * @brief Initializes the disk device management.
    296  *
    297  * This functions returns successful if the disk device management is already
    298  * initialized.  There is no protection against concurrent access.
    299  */
    300 rtems_status_code rtems_disk_io_initialize(void);
    301 
    302 /**
    303  * @brief Releases all resources allocated for disk device management.
    304  */
    305 rtems_status_code rtems_disk_io_done(void);
    306 
    307 /** @} */
    308 
    309 /** @} */
    310 
    311355#ifdef __cplusplus
    312356}
  • cpukit/libblock/include/rtems/ramdisk.h

    rb83c7ba9 re41369ef  
    7575 */
    7676extern size_t rtems_ramdisk_configuration_size;
    77 
    78 int ramdisk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
    7977
    8078/**
     
    143141extern const rtems_driver_address_table ramdisk_ops;
    144142
     143int ramdisk_ioctl(rtems_disk_device *dd, uint32_t req, void *argp);
     144
    145145/**
    146146 * @brief Allocates and initializes a RAM disk descriptor.
     
    154154 * if no memory is available.
    155155 *
     156 * @note
     157 * Runtime configuration example:
    156158 * @code
     159 * #include <rtems.h>
     160 * #include <rtems/libio.h>
     161 * #include <rtems/ramdisk.h>
     162 *
    157163 * rtems_status_code create_ramdisk(
    158164 *   const char *disk_name_path,
  • cpukit/libblock/src/diskdevs.c

    rb83c7ba9 re41369ef  
    44 * @ingroup rtems_disk
    55 *
    6  * Block device disk management.
     6 * @brief Block device disk management implementation.
    77 */
    88 
     
    1111 * Author: Victor V. Vengerov <vvv@oktet.ru>
    1212 *
     13 * Copyright (c) 2009 embedded brains GmbH.
     14 *
    1315 * @(#) $Id$
    1416 */
     
    1820#endif
    1921
     22#include <stdlib.h>
     23#include <unistd.h>
     24#include <string.h>
     25
    2026#include <rtems.h>
    2127#include <rtems/libio.h>
    22 #include <stdlib.h>
    23 #include <unistd.h>     /* unlink */
    24 #include <string.h>
    25 
    26 #include "rtems/diskdevs.h"
    27 #include "rtems/bdbuf.h"
    28 
    29 #define DISKTAB_INITIAL_SIZE 32
     28#include <rtems/diskdevs.h>
     29#include <rtems/blkdev.h>
     30#include <rtems/bdbuf.h>
     31
     32#define DISKTAB_INITIAL_SIZE 8
    3033
    3134/* Table of disk devices having the same major number */
    3235typedef struct rtems_disk_device_table {
    33     rtems_disk_device **minor; /* minor-indexed disk device table */
    34     uint32_t            size;            /* Number of entries in the table */
     36  rtems_disk_device **minor; /* minor-indexed disk device table */
     37  rtems_device_minor_number size; /* Number of entries in the table */
    3538} rtems_disk_device_table;
    3639
     
    3942
    4043/* Number of allocated entries in disktab table */
    41 static uint32_t disktab_size;
     44static rtems_device_major_number disktab_size;
    4245
    4346/* Mutual exclusion semaphore for disk devices table */
    4447static rtems_id diskdevs_mutex;
    45 
    46 /* Flag meaning that disk I/O, buffering etc. already has been initialized. */
    47 static bool disk_io_initialized = false;
    4848
    4949/* diskdevs data structures protection flag.
     
    6060static volatile bool diskdevs_protected;
    6161
    62 /* create_disk_entry --
    63  *     Return pointer to the disk_entry structure for the specified device, or
    64  *     create one if it is not exists.
    65  *
    66  * PARAMETERS:
    67  *     dev - device id (major, minor)
    68  *
    69  * RETURNS:
    70  *     pointer to the disk device descriptor entry, or NULL if no memory
    71  *     available for its creation.
    72  */
    73 static rtems_disk_device *
    74 create_disk_entry(dev_t dev)
    75 {
    76     rtems_device_major_number major;
    77     rtems_device_minor_number minor;
    78     rtems_disk_device **d;
    79 
    80     rtems_filesystem_split_dev_t (dev, major, minor);
    81 
    82     if (major >= disktab_size)
    83     {
    84         rtems_disk_device_table *p;
    85         uint32_t newsize;
    86         uint32_t i;
    87         newsize = disktab_size * 2;
    88         if (major >= newsize)
    89             newsize = major + 1;
    90         p = realloc(disktab, sizeof(rtems_disk_device_table) * newsize);
    91         if (p == NULL)
    92             return NULL;
    93         disktab = p;
    94         p += disktab_size;
    95         for (i = disktab_size; i < newsize; i++, p++)
    96         {
    97             p->minor = NULL;
    98             p->size = 0;
    99         }
    100         disktab_size = newsize;
    101     }
    102 
    103     if ((disktab[major].minor == NULL) ||
    104         (minor >= disktab[major].size))
    105     {
    106         uint32_t            newsize;
    107         rtems_disk_device **p;
    108         uint32_t            i;
    109         uint32_t            s = disktab[major].size;
    110 
    111         if (s == 0)
    112             newsize = DISKTAB_INITIAL_SIZE;
    113         else
    114             newsize = s * 2;
    115         if (minor >= newsize)
    116             newsize = minor + 1;
    117 
    118         p = realloc(disktab[major].minor,
    119                     sizeof(rtems_disk_device *) * newsize);
    120         if (p == NULL)
    121             return NULL;
    122         disktab[major].minor = p;
    123         p += s;
    124         for (i = s; i < newsize; i++, p++)
    125             *p = NULL;
    126         disktab[major].size = newsize;
    127     }
    128 
    129     d = disktab[major].minor + minor;
    130     if (*d == NULL)
    131     {
    132         *d = calloc(1, sizeof(rtems_disk_device));
    133     }
    134     return *d;
    135 }
    136 
    137 /* get_disk_entry --
    138  *     Get disk device descriptor by device number.
    139  *
    140  * PARAMETERS:
    141  *     dev - block device number
    142  *
    143  * RETURNS:
    144  *     Pointer to the disk device descriptor corresponding to the specified
    145  *     device number, or NULL if disk device with such number not exists.
    146  */
     62static rtems_status_code
     63disk_lock(void)
     64{
     65  rtems_status_code sc = RTEMS_SUCCESSFUL;
     66
     67  sc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     68  if (sc == RTEMS_SUCCESSFUL) {
     69    diskdevs_protected = true;
     70
     71    return RTEMS_SUCCESSFUL;
     72  } else {
     73    return RTEMS_NOT_CONFIGURED;
     74  }
     75}
     76
     77static void
     78disk_unlock(void)
     79{
     80  rtems_status_code sc = RTEMS_SUCCESSFUL;
     81
     82  diskdevs_protected = false;
     83
     84  sc = rtems_semaphore_release(diskdevs_mutex);
     85  if (sc != RTEMS_SUCCESSFUL) {
     86    /* FIXME: Error number */
     87    rtems_fatal_error_occurred(0xdeadbeef);
     88  }
     89}
     90
    14791static rtems_disk_device *
    14892get_disk_entry(dev_t dev)
    14993{
    150     rtems_device_major_number major;
    151     rtems_device_minor_number minor;
    152     rtems_disk_device_table *dtab;
    153 
    154     rtems_filesystem_split_dev_t (dev, major, minor);
    155 
    156     if ((major >= disktab_size) || (disktab == NULL))
    157         return NULL;
    158 
    159     dtab = disktab + major;
    160 
    161     if ((minor >= dtab->size) || (dtab->minor == NULL))
    162         return NULL;
    163 
    164     return dtab->minor[minor];
    165 }
    166 
    167 /* create_disk --
    168  *     Check that disk entry for specified device number is not defined
    169  *     and create it.
    170  *
    171  * PARAMETERS:
    172  *     dev        - device identifier (major, minor numbers)
    173  *     name       - character name of device (e.g. /dev/hda)
    174  *     disdev     - placeholder for pointer to created disk descriptor
    175  *
    176  * RETURNS:
    177  *     RTEMS_SUCCESSFUL if disk entry successfully created, or
    178  *     error code if error occured (device already registered,
    179  *     no memory available).
    180  */
     94  rtems_device_major_number major = 0;
     95  rtems_device_minor_number minor = 0;
     96
     97  rtems_filesystem_split_dev_t(dev, major, minor);
     98
     99  if (major < disktab_size && disktab != NULL) {
     100    rtems_disk_device_table *dtab = disktab + major;
     101
     102    if (minor < dtab->size && dtab->minor != NULL) {
     103      rtems_disk_device *dd = dtab->minor [minor];
     104
     105      if (dd != NULL && !dd->deleted) {
     106        ++dd->uses;
     107
     108        return dd;
     109      }
     110    }
     111  }
     112
     113  return NULL;
     114}
     115
     116static rtems_disk_device **
     117create_disk_table_entry(dev_t dev)
     118{
     119  rtems_device_major_number major = 0;
     120  rtems_device_minor_number minor = 0;
     121
     122  rtems_filesystem_split_dev_t(dev, major, minor);
     123
     124  if (major >= disktab_size) {
     125    rtems_disk_device_table *table = disktab;
     126    rtems_device_major_number old_size = disktab_size;
     127    rtems_device_major_number new_size = 2 * old_size;
     128
     129    if (major >= new_size) {
     130      new_size = major + 1;
     131    }
     132
     133    table = realloc(table, new_size * sizeof(*table));
     134    if (table == NULL) {
     135      return NULL;
     136    }
     137
     138    memset(table + old_size, 0, (new_size - old_size) * sizeof(*table));
     139    disktab = table;
     140    disktab_size = new_size;
     141  }
     142
     143  if (disktab [major].minor == NULL || minor >= disktab[major].size) {
     144    rtems_disk_device **table = disktab [major].minor;
     145    rtems_device_minor_number old_size = disktab [major].size;
     146    rtems_device_minor_number new_size = 0;
     147
     148    if (old_size == 0) {
     149      new_size = DISKTAB_INITIAL_SIZE;
     150    } else {
     151      new_size = 2 * old_size;
     152    }
     153    if (minor >= new_size) {
     154      new_size = minor + 1;
     155    }
     156
     157    table = realloc(table, new_size * sizeof(*table));
     158    if (table == NULL) {
     159      return NULL;
     160    }
     161
     162    memset(table + old_size, 0, (new_size - old_size) * sizeof(*table));
     163    disktab [major].minor = table;
     164    disktab [major].size = new_size;
     165  }
     166
     167  return disktab [major].minor + minor;
     168}
     169
    181170static rtems_status_code
    182 create_disk(dev_t dev, const char *name, rtems_disk_device **diskdev)
    183 {
    184     rtems_disk_device *dd;
    185     char *n;
    186 
    187     dd = get_disk_entry(dev);
    188     if (dd != NULL)
    189     {
    190         return RTEMS_RESOURCE_IN_USE;
    191     }
    192 
    193     if (name == NULL)
    194     {
    195         n = NULL;
    196     }
    197     else
    198     {
    199         int nlen = strlen(name) + 1;
    200         n = malloc(nlen);
    201         if (n == NULL)
    202             return RTEMS_NO_MEMORY;
    203         strncpy(n, name, nlen);
    204     }
    205 
    206     dd = create_disk_entry(dev);
    207     if (dd == NULL)
    208     {
    209         free(n);
    210         return RTEMS_NO_MEMORY;
    211     }
    212 
    213     dd->dev = dev;
    214     dd->name = n;
    215 
    216     *diskdev = dd;
    217 
    218     return RTEMS_SUCCESSFUL;
     171create_disk(dev_t dev, const char *name, rtems_disk_device **dd_ptr)
     172{
     173  rtems_status_code sc = RTEMS_SUCCESSFUL;
     174  rtems_disk_device **dd_entry = create_disk_table_entry(dev);
     175  rtems_disk_device *dd = NULL;
     176  char *alloc_name = NULL;
     177
     178  if (dd_entry == NULL) {
     179    return RTEMS_NO_MEMORY;
     180  }
     181
     182  if (*dd_entry != NULL) {
     183    return RTEMS_RESOURCE_IN_USE;
     184  }
     185
     186  dd = malloc(sizeof(*dd));
     187  if (dd == NULL) {
     188    return RTEMS_NO_MEMORY;
     189  }
     190
     191  if (name != NULL) {
     192    alloc_name = strdup(name);
     193   
     194    if (alloc_name == NULL) {
     195      free(dd);
     196
     197      return RTEMS_NO_MEMORY;
     198    }
     199  }
     200
     201  if (name != NULL) {
     202    rtems_device_major_number major = 0;
     203    rtems_device_minor_number minor = 0;
     204
     205    rtems_filesystem_split_dev_t(dev, major, minor);
     206
     207    sc = rtems_io_register_name(name, major, minor);
     208    if (sc != RTEMS_SUCCESSFUL) {
     209      free(alloc_name);
     210      free(dd);
     211
     212      return RTEMS_UNSATISFIED;
     213    }
     214  }
     215
     216  dd->dev = dev;
     217  dd->name = alloc_name;
     218  dd->uses = 0;
     219  dd->deleted = false;
     220
     221  *dd_entry = dd;
     222  *dd_ptr = dd;
     223
     224  return RTEMS_SUCCESSFUL;
    219225}
    220226
     
    222228  dev_t dev,
    223229  uint32_t block_size,
    224   rtems_blkdev_bnum disk_size,
     230  rtems_blkdev_bnum block_count,
    225231  rtems_block_device_ioctl handler,
    226232  void *driver_data,
     
    228234)
    229235{
    230     rtems_disk_device *dd;
    231     rtems_status_code rc;
    232     rtems_device_major_number major;
    233     rtems_device_minor_number minor;
    234 
    235     rtems_filesystem_split_dev_t (dev, major, minor);
    236 
    237     rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    238     if (rc != RTEMS_SUCCESSFUL)
    239         return rc;
    240     diskdevs_protected = true;
    241 
    242     rc = create_disk(dev, name, &dd);
    243     if (rc != RTEMS_SUCCESSFUL)
    244     {
    245         diskdevs_protected = false;
    246         rtems_semaphore_release(diskdevs_mutex);
    247         return rc;
    248     }
    249 
    250     dd->phys_dev = dd;
    251     dd->uses = 0;
    252     dd->start = 0;
    253     dd->size = disk_size;
    254     dd->block_size = dd->media_block_size = block_size;
    255     dd->ioctl = handler;
    256     dd->driver_data = driver_data;
    257 
    258     rc = rtems_io_register_name(name, major, minor);
    259 
    260     if (handler (dd, RTEMS_BLKDEV_CAPABILITIES, &dd->capabilities) < 0)
    261       dd->capabilities = 0;
    262    
    263     diskdevs_protected = false;
    264     rtems_semaphore_release(diskdevs_mutex);
    265 
    266     return rc;
     236  rtems_disk_device *dd = NULL;
     237  rtems_status_code sc = RTEMS_SUCCESSFUL;
     238
     239  if (handler == NULL) {
     240    return RTEMS_INVALID_ADDRESS;
     241  }
     242
     243  if (block_size == 0) {
     244    return RTEMS_INVALID_NUMBER;
     245  }
     246
     247  sc = disk_lock();
     248  if (sc != RTEMS_SUCCESSFUL) {
     249    return sc;
     250  }
     251
     252  sc = create_disk(dev, name, &dd);
     253  if (sc != RTEMS_SUCCESSFUL) {
     254    disk_unlock();
     255
     256    return sc;
     257  }
     258
     259  dd->phys_dev = dd;
     260  dd->start = 0;
     261  dd->size = block_count;
     262  dd->block_size = dd->media_block_size = block_size;
     263  dd->ioctl = handler;
     264  dd->driver_data = driver_data;
     265
     266  if ((*handler)(dd, RTEMS_BLKDEV_CAPABILITIES, &dd->capabilities) < 0) {
     267    dd->capabilities = 0;
     268  }
     269 
     270  disk_unlock();
     271
     272  return RTEMS_SUCCESSFUL;
     273}
     274
     275static bool
     276is_physical_disk(const rtems_disk_device *dd)
     277{
     278  return dd->phys_dev == dd;
    267279}
    268280
     
    270282  dev_t dev,
    271283  dev_t phys,
    272   rtems_blkdev_bnum start,
    273   rtems_blkdev_bnum size,
     284  rtems_blkdev_bnum begin_block,
     285  rtems_blkdev_bnum block_count,
    274286  const char *name
    275287)
    276288{
     289  rtems_status_code sc = RTEMS_SUCCESSFUL;
     290  rtems_disk_device *physical_disk = NULL;
    277291  rtems_disk_device *dd = NULL;
    278   rtems_disk_device *pdd = NULL;
    279   rtems_status_code rc = RTEMS_SUCCESSFUL;
     292  rtems_blkdev_bnum end_block = begin_block + block_count;
     293
     294  sc = disk_lock();
     295  if (sc != RTEMS_SUCCESSFUL) {
     296    return sc;
     297  }
     298
     299  physical_disk = get_disk_entry(phys);
     300  if (physical_disk == NULL || !is_physical_disk(physical_disk)) {
     301    if (physical_disk != NULL) {
     302      --physical_disk->uses;
     303    }
     304    disk_unlock();
     305
     306    return RTEMS_INVALID_ID;
     307  }
     308
     309  if (
     310    begin_block >= physical_disk->size
     311      || end_block <= begin_block
     312      || end_block > physical_disk->size
     313  ) {
     314    --physical_disk->uses;
     315    disk_unlock();
     316
     317    return RTEMS_INVALID_NUMBER;
     318  }
     319
     320  sc = create_disk(dev, name, &dd);
     321  if (sc != RTEMS_SUCCESSFUL) {
     322    --physical_disk->uses;
     323    disk_unlock();
     324
     325    return sc;
     326  }
     327
     328  dd->phys_dev = physical_disk;
     329  dd->start = begin_block;
     330  dd->size = block_count;
     331  dd->block_size = dd->media_block_size = physical_disk->block_size;
     332  dd->ioctl = physical_disk->ioctl;
     333  dd->driver_data = physical_disk->driver_data;
     334
     335  disk_unlock();
     336
     337  return RTEMS_SUCCESSFUL;
     338}
     339
     340static void
     341free_disk_device(rtems_disk_device *dd)
     342{
     343  if (is_physical_disk(dd)) {
     344    (*dd->ioctl)(dd, RTEMS_BLKIO_DELETED, NULL);
     345  }
     346  if (dd->name != NULL) {
     347    unlink(dd->name);
     348    free(dd->name);
     349  }
     350  free(dd);
     351}
     352
     353static void
     354rtems_disk_cleanup(rtems_disk_device *disk_to_remove)
     355{
     356  rtems_disk_device *const physical_disk = disk_to_remove->phys_dev;
    280357  rtems_device_major_number major = 0;
    281358  rtems_device_minor_number minor = 0;
    282   rtems_blkdev_bnum end = start + size;
    283 
    284   rtems_filesystem_split_dev_t (dev, major, minor);
    285 
    286   rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    287   if (rc != RTEMS_SUCCESSFUL) {
    288     return rc;
    289   }
    290 
    291   diskdevs_protected = true;
    292 
    293   pdd = get_disk_entry(phys);
    294   if (
    295     pdd == NULL
    296       || pdd != pdd->phys_dev
    297       || start >= pdd->size
    298       || end <= start
    299       || end > pdd->size
    300   ) {
    301     diskdevs_protected = false;
    302     rtems_semaphore_release(diskdevs_mutex);
    303     return RTEMS_INVALID_NUMBER;
    304   }
    305 
    306   rc = create_disk(dev, name, &dd);
    307   if (rc != RTEMS_SUCCESSFUL) {
    308     diskdevs_protected = false;
    309     rtems_semaphore_release(diskdevs_mutex);
    310     return rc;
    311   }
    312 
    313   dd->phys_dev = pdd;
    314   dd->uses = 0;
    315   dd->start = start;
    316   dd->size = size;
    317   dd->block_size = dd->media_block_size = pdd->block_size;
    318   dd->ioctl = pdd->ioctl;
    319   dd->driver_data = pdd->driver_data;
    320 
    321   rc = rtems_io_register_name(name, major, minor);
    322 
    323   diskdevs_protected = false;
    324   rc = rtems_semaphore_release(diskdevs_mutex);
    325 
    326   return rc;
    327 }
    328 
    329 rtems_status_code
    330 rtems_disk_delete(dev_t dev)
    331 {
    332   rtems_status_code rc = RTEMS_SUCCESSFUL;
    333   rtems_device_major_number maj = 0;
    334   rtems_device_minor_number min = 0;
    335   rtems_disk_device *dd = NULL;
    336   bool physical_disk = true;
    337 
    338   rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    339   if (rc != RTEMS_SUCCESSFUL) {
    340     return rc;
    341   }
    342   diskdevs_protected = true;
    343 
    344   /* Check if we have a physical or logical disk */
    345   dd = get_disk_entry(dev);
    346   if (dd == NULL) {
    347     return RTEMS_INVALID_NUMBER;
    348   }
    349   physical_disk = dd->phys_dev == dd;
    350 
    351   if (physical_disk) {
    352     unsigned used = 0;
    353 
    354     /* Check if this device is in use -- calculate usage counter */
    355     for (maj = 0; maj < disktab_size; maj++) {
    356       rtems_disk_device_table *dtab = disktab + maj;
    357       if (dtab != NULL) {
    358         for (min = 0; min < dtab->size; min++) {
    359           dd = dtab->minor[min];
    360           if ((dd != NULL) && (dd->phys_dev->dev == dev)) {
    361             used += dd->uses;
     359
     360  if (physical_disk->deleted) {
     361    dev_t dev = physical_disk->dev;
     362    unsigned deleted_count = 0;
     363
     364    for (major = 0; major < disktab_size; ++major) {
     365      rtems_disk_device_table *dtab = disktab + major;
     366
     367      for (minor = 0; minor < dtab->size; ++minor) {
     368        rtems_disk_device *dd = dtab->minor [minor];
     369
     370        if (dd != NULL && dd->phys_dev->dev == dev && dd != physical_disk) {
     371          if (dd->uses == 0) {
     372            ++deleted_count;
     373            dtab->minor [minor] = NULL;
     374            free_disk_device(dd);
     375          } else {
     376            dd->deleted = true;
    362377          }
    363378        }
     
    365380    }
    366381
    367     if (used != 0) {
    368       diskdevs_protected = false;
    369       rtems_semaphore_release(diskdevs_mutex);
    370       return RTEMS_RESOURCE_IN_USE;
    371     }
    372 
    373     /* Delete this device and all of its logical devices */
    374     for (maj = 0; maj < disktab_size; maj++) {
    375       rtems_disk_device_table *dtab = disktab + maj;
    376       if (dtab != NULL) {
    377         for (min = 0; min < dtab->size; min++) {
    378           dd = dtab->minor[min];
    379           if ((dd != NULL) && (dd->phys_dev->dev == dev)) {
    380             unlink(dd->name);
    381             free(dd->name);
    382             free(dd);
    383             dtab->minor[min] = NULL;
    384           }
    385         }
    386       }
     382    physical_disk->uses -= deleted_count;
     383    if (physical_disk->uses == 0) {
     384      rtems_filesystem_split_dev_t(physical_disk->dev, major, minor);
     385      disktab [major].minor [minor] = NULL;
     386      free_disk_device(physical_disk);
    387387    }
    388388  } else {
    389     rtems_filesystem_split_dev_t(dev, maj, min);
    390     disktab[maj].minor[min] = NULL;
    391     unlink(dd->name);
    392     free(dd->name);
    393     free(dd);
    394   }
    395 
    396   diskdevs_protected = false;
    397   rc = rtems_semaphore_release(diskdevs_mutex);
    398   return rc;
     389    if (disk_to_remove->uses == 0) {
     390      --physical_disk->uses;
     391      rtems_filesystem_split_dev_t(disk_to_remove->dev, major, minor);
     392      disktab [major].minor [minor] = NULL;
     393      free_disk_device(disk_to_remove);
     394    }
     395  }
     396}
     397
     398rtems_status_code
     399rtems_disk_delete(dev_t dev)
     400{
     401  rtems_status_code sc = RTEMS_SUCCESSFUL;
     402  rtems_disk_device *dd = NULL;
     403
     404  sc = disk_lock();
     405  if (sc != RTEMS_SUCCESSFUL) {
     406    return sc;
     407  }
     408
     409  dd = get_disk_entry(dev);
     410  if (dd == NULL) {
     411    disk_unlock();
     412
     413    return RTEMS_INVALID_ID;
     414  }
     415
     416  --dd->uses;
     417  dd->deleted = true;
     418  rtems_disk_cleanup(dd);
     419
     420  disk_unlock();
     421
     422  return RTEMS_SUCCESSFUL;
    399423}
    400424
     
    402426rtems_disk_obtain(dev_t dev)
    403427{
    404     rtems_interrupt_level level;
    405     rtems_disk_device *dd;
    406     rtems_status_code rc;
    407 
    408     rtems_interrupt_disable(level);
    409     if (diskdevs_protected)
    410     {
    411         rtems_interrupt_enable(level);
    412         rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT,
    413                                     RTEMS_NO_TIMEOUT);
    414         if (rc != RTEMS_SUCCESSFUL)
    415             return NULL;
    416         diskdevs_protected = true;
    417         dd = get_disk_entry(dev);
    418         dd->uses++;
    419         diskdevs_protected = false;
    420         rtems_semaphore_release(diskdevs_mutex);
    421         return dd;
    422     }
    423     else
    424     {
    425         /* Frequent and quickest case */
    426         dd = get_disk_entry(dev);
    427         dd->uses++;
    428         rtems_interrupt_enable(level);
    429         return dd;
    430     }
     428  rtems_status_code sc = RTEMS_SUCCESSFUL;
     429  rtems_disk_device *dd = NULL;
     430  rtems_interrupt_level level;
     431
     432  rtems_interrupt_disable(level);
     433  if (!diskdevs_protected) {
     434    /* Frequent and quickest case */
     435    dd = get_disk_entry(dev);
     436    rtems_interrupt_enable(level);
     437  } else {
     438    rtems_interrupt_enable(level);
     439
     440    sc = disk_lock();
     441    if (sc == RTEMS_SUCCESSFUL) {
     442      dd = get_disk_entry(dev);
     443      disk_unlock();
     444    }
     445  }
     446
     447  return dd;
    431448}
    432449
     
    434451rtems_disk_release(rtems_disk_device *dd)
    435452{
    436     rtems_interrupt_level level;
    437     rtems_interrupt_disable(level);
    438     dd->uses--;
    439     rtems_interrupt_enable(level);
    440     return RTEMS_SUCCESSFUL;
     453  rtems_interrupt_level level;
     454  dev_t dev = dd->dev;
     455  unsigned uses = 0;
     456  bool deleted = false;
     457
     458  rtems_interrupt_disable(level);
     459  uses = --dd->uses;
     460  deleted = dd->deleted;
     461  rtems_interrupt_enable(level);
     462
     463  if (uses == 0 && deleted) {
     464    rtems_disk_delete(dev);
     465  }
     466
     467  return RTEMS_SUCCESSFUL;
    441468}
    442469
     
    476503rtems_disk_io_initialize(void)
    477504{
    478     rtems_status_code rc;
    479 
    480     if (disk_io_initialized)
    481         return RTEMS_SUCCESSFUL;
    482 
    483     disktab_size = DISKTAB_INITIAL_SIZE;
    484     disktab = calloc(disktab_size, sizeof(rtems_disk_device_table));
    485     if (disktab == NULL)
    486         return RTEMS_NO_MEMORY;
    487 
    488     diskdevs_protected = false;
    489     rc = rtems_semaphore_create(
    490         rtems_build_name('D', 'D', 'E', 'V'), 1,
    491         RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
    492         RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0, &diskdevs_mutex);
    493 
    494     if (rc != RTEMS_SUCCESSFUL)
    495     {
    496         free(disktab);
    497         return rc;
    498     }
    499 
    500     rc = rtems_bdbuf_init();
    501 
    502     if (rc != RTEMS_SUCCESSFUL)
    503     {
    504         rtems_semaphore_delete(diskdevs_mutex);
    505         free(disktab);
    506         return rc;
    507     }
    508 
    509     disk_io_initialized = 1;
     505  rtems_status_code sc = RTEMS_SUCCESSFUL;
     506  rtems_device_major_number size = DISKTAB_INITIAL_SIZE;
     507
     508  if (disktab_size > 0) {
    510509    return RTEMS_SUCCESSFUL;
     510  }
     511
     512  disktab = calloc(size, sizeof(rtems_disk_device_table));
     513  if (disktab == NULL) {
     514    return RTEMS_NO_MEMORY;
     515  }
     516
     517  diskdevs_protected = false;
     518  sc = rtems_semaphore_create(
     519    rtems_build_name('D', 'D', 'E', 'V'),
     520    1,
     521    RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY
     522      | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
     523    0,
     524    &diskdevs_mutex
     525  );
     526  if (sc != RTEMS_SUCCESSFUL) {
     527    free(disktab);
     528
     529    return RTEMS_NO_MEMORY;
     530  }
     531
     532  sc = rtems_bdbuf_init();
     533  if (sc != RTEMS_SUCCESSFUL) {
     534    rtems_semaphore_delete(diskdevs_mutex);
     535    free(disktab);
     536
     537    return RTEMS_UNSATISFIED;
     538  }
     539
     540  disktab_size = size;
     541
     542  return RTEMS_SUCCESSFUL;
    511543}
    512544
     
    514546rtems_disk_io_done(void)
    515547{
    516     rtems_device_major_number maj;
    517     rtems_device_minor_number min;
    518     rtems_status_code rc;
    519 
    520     /* Free data structures */
    521     for (maj = 0; maj < disktab_size; maj++)
    522     {
    523         rtems_disk_device_table *dtab = disktab + maj;
    524         if (dtab != NULL)
    525         {
    526             for (min = 0; min < dtab->size; min++)
    527             {
    528                 rtems_disk_device *dd = dtab->minor[min];
    529                 unlink(dd->name);
    530                 free(dd->name);
    531                 free(dd);
    532             }
    533             free(dtab);
    534         }
    535     }
    536     free(disktab);
    537 
    538     rc = rtems_semaphore_delete(diskdevs_mutex);
    539 
    540     disk_io_initialized = 0;
    541     return rc;
    542 }
     548  rtems_device_major_number major = 0;
     549  rtems_device_minor_number minor = 0;
     550
     551  for (major = 0; major < disktab_size; ++major) {
     552    rtems_disk_device_table *dtab = disktab + major;
     553
     554    for (minor = 0; minor < dtab->size; ++minor) {
     555      rtems_disk_device *dd = dtab->minor [minor];
     556
     557      if (dd != NULL) {
     558        free_disk_device(dd);
     559      }
     560    }
     561    free(dtab->minor);
     562  }
     563  free(disktab);
     564
     565  rtems_semaphore_delete(diskdevs_mutex);
     566
     567  diskdevs_mutex = RTEMS_ID_NONE;
     568  disktab = NULL;
     569  disktab_size = 0;
     570
     571  return RTEMS_SUCCESSFUL;
     572}
  • cpukit/libblock/src/ramdisk-driver.c

    rb83c7ba9 re41369ef  
    1414 */
    1515
    16 #include <stdio.h>
     16/* FIXME: How to set this define? */
     17#if !defined(RTEMS_RAMDISK_TRACE)
     18    #define RTEMS_RAMDISK_TRACE 0
     19#endif
     20
    1721#include <stdlib.h>
    1822#include <errno.h>
    1923#include <string.h>
    20 #include <inttypes.h>
     24
     25#if RTEMS_RAMDISK_TRACE
     26    #include <stdio.h>
     27#endif
    2128
    2229#include <rtems.h>
    2330#include <rtems/ramdisk.h>
    2431
    25 static void
    26 rtems_ramdisk_printf (const ramdisk *rd, const char *format, ...)
    27 {
    28   if (rd->trace)
    29   {
    30     va_list args;
    31     va_start (args, format);
    32     printf ("ramdisk:");
    33     vprintf (format, args);
    34     printf ("\n");
    35   }
    36 }
     32#if RTEMS_RAMDISK_TRACE
     33    static void
     34    rtems_ramdisk_printf (const ramdisk *rd, const char *format, ...)
     35    {
     36        if (rd->trace)
     37        {
     38            va_list args;
     39            va_start (args, format);
     40            printf ("ramdisk:");
     41            vprintf (format, args);
     42            printf ("\n");
     43        }
     44    }
     45#endif
    3746
    3847static int
     
    4352    rtems_blkdev_sg_buffer *sg;
    4453
     54#if RTEMS_RAMDISK_TRACE
    4555    rtems_ramdisk_printf (rd, "ramdisk read: start=%d, blocks=%d",
    4656                          req->bufs[0].block, req->bufnum);
     57#endif
    4758
    4859    for (i = 0, sg = req->bufs; i < req->bufnum; i++, sg++)
    4960    {
     61#if RTEMS_RAMDISK_TRACE
    5062        rtems_ramdisk_printf (rd, "ramdisk read: buf=%d block=%d length=%d off=%d addr=%p",
    5163                              i, sg->block, sg->length, sg->block * rd->block_size,
    5264                              from + (sg->block * rd->block_size));
     65#endif
    5366        memcpy(sg->buffer, from + (sg->block * rd->block_size), sg->length);
    5467    }
     
    6477    rtems_blkdev_sg_buffer *sg;
    6578
     79#if RTEMS_RAMDISK_TRACE
    6680    rtems_ramdisk_printf (rd, "ramdisk write: start=%d, blocks=%d",
    6781                          req->bufs[0].block, req->bufnum);
     82#endif
    6883    for (i = 0, sg = req->bufs; i < req->bufnum; i++, sg++)
    6984    {
     85#if RTEMS_RAMDISK_TRACE
    7086        rtems_ramdisk_printf (rd, "ramdisk write: buf=%d block=%d length=%d off=%d addr=%p",
    7187                              i, sg->block, sg->length, sg->block * rd->block_size,
    7288                              to + (sg->block * rd->block_size));
     89#endif
    7390        memcpy(to + (sg->block * rd->block_size), sg->buffer, sg->length);
    7491    }
Note: See TracChangeset for help on using the changeset viewer.