From 945884fe9fc662bcce68f5ed61127c3e6ddef467 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Thu, 6 Aug 2009 03:58:09 +0000 Subject: 2009-08-06 Chris Johns * libblock/src/bdbuf.c: Fix group user logic. * libblock/include/rtems/blkdev.h, libblock/src/blkdev.c, libblock/src/nvdisk.c, libblock/src/flashdisk.c: Add set block size, and get media block size support. --- cpukit/ChangeLog | 7 ++ cpukit/libblock/include/rtems/blkdev.h | 24 ++++-- cpukit/libblock/src/bdbuf.c | 129 +++++++++++++++++++++++++-------- cpukit/libblock/src/blkdev.c | 51 +++++++++++++ cpukit/libblock/src/flashdisk.c | 2 +- cpukit/libblock/src/nvdisk.c | 2 +- cpukit/libblock/src/ramdisk.c | 9 ++- 7 files changed, 181 insertions(+), 43 deletions(-) diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog index 00350746cc..8050494713 100644 --- a/cpukit/ChangeLog +++ b/cpukit/ChangeLog @@ -1,3 +1,10 @@ +2009-08-06 Chris Johns + + * libblock/src/bdbuf.c: Fix group user logic. + * libblock/include/rtems/blkdev.h, libblock/src/blkdev.c, + libblock/src/nvdisk.c, libblock/src/flashdisk.c: Add set block + size, and get media block size support. + 2009-08-05 Joel Sherrill * posix/src/sigaction.c: _POSIX_signals_Clear_process_signals now takes diff --git a/cpukit/libblock/include/rtems/blkdev.h b/cpukit/libblock/include/rtems/blkdev.h index 40a7541731..bd329c7bdd 100644 --- a/cpukit/libblock/include/rtems/blkdev.h +++ b/cpukit/libblock/include/rtems/blkdev.h @@ -48,9 +48,9 @@ typedef uint32_t rtems_blkdev_bnum; * Block device request type. */ typedef enum rtems_blkdev_request_op { - RTEMS_BLKDEV_REQ_READ, - RTEMS_BLKDEV_REQ_WRITE, - RTEMS_BLKDEV_CAPABILITIES + RTEMS_BLKDEV_REQ_READ, /**< Read the requested blocks of data. */ + RTEMS_BLKDEV_REQ_WRITE, /**< Write the requested blocks of data. */ + RTEMS_BLKDEV_CAPABILITIES /**< Return the driver capabilities set. */ } rtems_blkdev_request_op; /** @@ -160,10 +160,12 @@ typedef struct rtems_blkdev_request { * @{ */ -#define RTEMS_BLKIO_REQUEST _IOWR('B', 1, rtems_blkdev_request) -#define RTEMS_BLKIO_GETBLKSIZE _IO('B', 2) -#define RTEMS_BLKIO_GETSIZE _IO('B', 3) -#define RTEMS_BLKIO_SYNCDEV _IO('B', 4) +#define RTEMS_BLKIO_REQUEST _IOWR('B', 1, rtems_blkdev_request) +#define RTEMS_BLKIO_GETMEDIABLKSIZE _IO('B', 2) +#define RTEMS_BLKIO_GETBLKSIZE _IO('B', 3) +#define RTEMS_BLKIO_SETBLKSIZE _IO('B', 4) +#define RTEMS_BLKIO_GETSIZE _IO('B', 5) +#define RTEMS_BLKIO_SYNCDEV _IO('B', 6) /** @} */ @@ -242,6 +244,14 @@ rtems_blkdev_generic_ioctl( void * arg ); +/** + * Common IO control primitive. + * + * Use this in all block devices to handle the common set of ioctl requests. + */ +int +rtems_blkdev_ioctl(dev_t dev, uint32_t req, void *argp); + /** @} */ #ifdef __cplusplus diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c index 3a686f5757..8bf58ae928 100644 --- a/cpukit/libblock/src/bdbuf.c +++ b/cpukit/libblock/src/bdbuf.c @@ -134,22 +134,30 @@ typedef struct rtems_bdbuf_cache #define RTEMS_BLKDEV_FATAL_ERROR(n) \ (((uint32_t)'B' << 24) | ((uint32_t)(n) & (uint32_t)0x00FFFFFF)) -#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY RTEMS_BLKDEV_FATAL_ERROR(1) -#define RTEMS_BLKDEV_FATAL_BDBUF_SWAPOUT RTEMS_BLKDEV_FATAL_ERROR(2) -#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK RTEMS_BLKDEV_FATAL_ERROR(3) -#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(4) -#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_LOCK RTEMS_BLKDEV_FATAL_ERROR(5) -#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(6) -#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_1 RTEMS_BLKDEV_FATAL_ERROR(7) -#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_2 RTEMS_BLKDEV_FATAL_ERROR(8) -#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_3 RTEMS_BLKDEV_FATAL_ERROR(9) -#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAKE RTEMS_BLKDEV_FATAL_ERROR(10) -#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE RTEMS_BLKDEV_FATAL_ERROR(11) -#define RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM RTEMS_BLKDEV_FATAL_ERROR(12) -#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_CREATE RTEMS_BLKDEV_FATAL_ERROR(13) -#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_START RTEMS_BLKDEV_FATAL_ERROR(14) -#define BLKDEV_FATAL_BDBUF_SWAPOUT_RE RTEMS_BLKDEV_FATAL_ERROR(15) -#define BLKDEV_FATAL_BDBUF_SWAPOUT_TS RTEMS_BLKDEV_FATAL_ERROR(16) +#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_1 RTEMS_BLKDEV_FATAL_ERROR(1) +#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_2 RTEMS_BLKDEV_FATAL_ERROR(2) +#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_3 RTEMS_BLKDEV_FATAL_ERROR(3) +#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_4 RTEMS_BLKDEV_FATAL_ERROR(4) +#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_5 RTEMS_BLKDEV_FATAL_ERROR(5) +#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_6 RTEMS_BLKDEV_FATAL_ERROR(6) +#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_7 RTEMS_BLKDEV_FATAL_ERROR(7) +#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_8 RTEMS_BLKDEV_FATAL_ERROR(8) +#define RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_9 RTEMS_BLKDEV_FATAL_ERROR(9) +#define RTEMS_BLKDEV_FATAL_BDBUF_SWAPOUT RTEMS_BLKDEV_FATAL_ERROR(10) +#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK RTEMS_BLKDEV_FATAL_ERROR(11) +#define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(12) +#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_LOCK RTEMS_BLKDEV_FATAL_ERROR(13) +#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_UNLOCK RTEMS_BLKDEV_FATAL_ERROR(14) +#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_1 RTEMS_BLKDEV_FATAL_ERROR(15) +#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_2 RTEMS_BLKDEV_FATAL_ERROR(16) +#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAIT_3 RTEMS_BLKDEV_FATAL_ERROR(17) +#define RTEMS_BLKDEV_FATAL_BDBUF_CACHE_WAKE RTEMS_BLKDEV_FATAL_ERROR(18) +#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WAKE RTEMS_BLKDEV_FATAL_ERROR(19) +#define RTEMS_BLKDEV_FATAL_BDBUF_SO_NOMEM RTEMS_BLKDEV_FATAL_ERROR(20) +#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_CREATE RTEMS_BLKDEV_FATAL_ERROR(21) +#define RTEMS_BLKDEV_FATAL_BDBUF_SO_WK_START RTEMS_BLKDEV_FATAL_ERROR(22) +#define BLKDEV_FATAL_BDBUF_SWAPOUT_RE RTEMS_BLKDEV_FATAL_ERROR(23) +#define BLKDEV_FATAL_BDBUF_SWAPOUT_TS RTEMS_BLKDEV_FATAL_ERROR(24) /** * The events used in this code. These should be system events rather than @@ -876,9 +884,8 @@ rtems_bdbuf_wake (rtems_id sema, volatile uint32_t* waiters) * modified list. The disk image is forced to be snapshot at that moment in * time. * - * and you must - * hold the sync lock. The sync lock is used to block writes while a sync is - * active. + * @note Do not lower the group user count as the modified list is a user of + * the buffer. * * @param bd The bd to queue to the cache's modified list. */ @@ -961,14 +968,23 @@ rtems_bdbuf_group_realloc (rtems_bdbuf_group* group, size_t new_bds_per_group) b < group->bds_per_group; b++, bd += bufs_per_bd) { + if ((bd->state == RTEMS_BDBUF_STATE_MODIFIED) || + (bd->state == RTEMS_BDBUF_STATE_ACCESS) || + (bd->state == RTEMS_BDBUF_STATE_ACCESS_MODIFIED) || + (bd->state == RTEMS_BDBUF_STATE_SYNC) || + (bd->state == RTEMS_BDBUF_STATE_TRANSFER)) + rtems_fatal_error_occurred ((bd->state << 16) | + RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_8); + if ((bd->state == RTEMS_BDBUF_STATE_CACHED) || - (bd->state == RTEMS_BDBUF_STATE_MODIFIED) || (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD)) { if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0) - rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY); - rtems_chain_extract (&bd->link); + rtems_fatal_error_occurred ((bd->state << 16) | + RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_1); } + + rtems_chain_extract (&bd->link); } group->bds_per_group = new_bds_per_group; @@ -977,7 +993,10 @@ rtems_bdbuf_group_realloc (rtems_bdbuf_group* group, size_t new_bds_per_group) for (b = 0, bd = group->bdbuf; b < group->bds_per_group; b++, bd += bufs_per_bd) + { + bd->state = RTEMS_BDBUF_STATE_EMPTY; rtems_chain_prepend (&bdbuf_cache.ready, &bd->link); + } } /** @@ -1004,7 +1023,6 @@ rtems_bdbuf_get_next_bd (size_t bds_per_group, if (bd->group->bds_per_group == bds_per_group) { rtems_chain_extract (node); - bd->group->users++; return bd; } @@ -1429,7 +1447,7 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd, * Remove the buffer from the AVL tree. */ if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0) - rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY); + rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_2); } else { @@ -1471,12 +1489,12 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd, */ if ((bd->state != RTEMS_BDBUF_STATE_EMPTY) && (bd->state != RTEMS_BDBUF_STATE_READ_AHEAD)) - rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY); + rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_3); if (bd->state == RTEMS_BDBUF_STATE_READ_AHEAD) { if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0) - rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY); + rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_4); } } @@ -1491,7 +1509,7 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd, bd->waiters = 0; if (rtems_bdbuf_avl_insert (&bdbuf_cache.tree, bd) != 0) - rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY); + rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_5); return bd; } @@ -1552,7 +1570,7 @@ rtems_bdbuf_get_buffer (rtems_disk_device* dd, break; default: - rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY); + rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_6); } } @@ -1610,6 +1628,11 @@ rtems_bdbuf_get (dev_t device, else bd->state = RTEMS_BDBUF_STATE_ACCESS; + /* + * Indicate a buffer in this group is being used. + */ + bd->group->users++; + rtems_bdbuf_unlock_cache (); rtems_disk_release(dd); @@ -1734,6 +1757,11 @@ rtems_bdbuf_read (dev_t device, bd->state = RTEMS_BDBUF_STATE_TRANSFER; bd->error = 0; + /* + * The buffer will be passed to the driver so this buffer has a user. + */ + bd->group->users++; + /* * @todo The use of these req blocks is not a great design. The req is a * struct with a single 'bufs' declared in the req struct and the @@ -1816,10 +1844,38 @@ rtems_bdbuf_read (dev_t device, bd = req->bufs[b].user; bd->error = req->error; bd->state = RTEMS_BDBUF_STATE_READ_AHEAD; - rtems_bdbuf_release (bd); + bd->group->users--; + rtems_chain_prepend (&bdbuf_cache.ready, &bd->link); + + /* + * If there is an error remove the BD from the AVL tree as it does is + * invalid, then wake any threads that may be waiting. A thread may have + * been waiting for this block and assumed it was in the tree. + */ + if (bd->error) + { + bd->state = RTEMS_BDBUF_STATE_EMPTY; + if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0) + rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_9); + } + + if (bd->waiters) + rtems_bdbuf_wake (bdbuf_cache.access, &bdbuf_cache.access_waiters); + else + { + if (rtems_chain_has_only_one_node (&bdbuf_cache.ready)) + rtems_bdbuf_wake (bdbuf_cache.waiting, &bdbuf_cache.wait_waiters); + } } bd = req->bufs[0].user; + + /* + * One less user. We do this here then increment again so the case of the + * buffer in the the cache and no read leaves the user counts at the + * correct level. + */ + bd->group->users--; } /* @@ -1828,7 +1884,13 @@ rtems_bdbuf_read (dev_t device, if (bd->state == RTEMS_BDBUF_STATE_MODIFIED) bd->state = RTEMS_BDBUF_STATE_ACCESS_MODIFIED; else + { + /* + * The file system is a user of the buffer. + */ + bd->group->users++; bd->state = RTEMS_BDBUF_STATE_ACCESS; + } rtems_bdbuf_unlock_cache (); rtems_disk_release (dd); @@ -1969,12 +2031,13 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer* bd) case RTEMS_BDBUF_STATE_SYNC: case RTEMS_BDBUF_STATE_TRANSFER: bd->waiters++; - rtems_bdbuf_wait (&bdbuf_cache.transfer, &bdbuf_cache.transfer_waiters); + rtems_bdbuf_wait (&bdbuf_cache.transfer, + &bdbuf_cache.transfer_waiters); bd->waiters--; break; default: - rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY); + rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CONSISTENCY_7); } } @@ -2211,6 +2274,10 @@ rtems_bdbuf_swapout_write (rtems_bdbuf_swapout_transfer* transfer) bd = transfer->write_req->bufs[b].user; bd->state = RTEMS_BDBUF_STATE_CACHED; bd->error = 0; + + /* + * The buffer is now not modified so lower the user count for the group. + */ bd->group->users--; rtems_chain_append (&bdbuf_cache.lru, &bd->link); diff --git a/cpukit/libblock/src/blkdev.c b/cpukit/libblock/src/blkdev.c index 25fe66d0e0..0411d47dba 100644 --- a/cpukit/libblock/src/blkdev.c +++ b/cpukit/libblock/src/blkdev.c @@ -17,6 +17,7 @@ #include "config.h" #endif +#include #include #include @@ -218,10 +219,18 @@ rtems_blkdev_generic_ioctl( switch (args->command) { + case RTEMS_BLKIO_GETMEDIABLKSIZE: + args->ioctl_return = dd->media_block_size; + break; + case RTEMS_BLKIO_GETBLKSIZE: args->ioctl_return = dd->block_size; break; + case RTEMS_BLKIO_SETBLKSIZE: + dd->block_size = *((size_t*) args->buffer); + break; + case RTEMS_BLKIO_GETSIZE: args->ioctl_return = dd->size; break; @@ -248,3 +257,45 @@ rtems_blkdev_generic_ioctl( return RTEMS_SUCCESSFUL; } + +int +rtems_blkdev_ioctl(dev_t dev, uint32_t req, void *argp) +{ + rtems_disk_device *dd; + size_t *arg_size = argp; + + dd = rtems_disk_obtain(dev); + if (dd == NULL) + { + errno = ENODEV; + return -1; + } + + switch (req) + { + case RTEMS_BLKIO_GETMEDIABLKSIZE: + *arg_size = dd->media_block_size; + break; + + case RTEMS_BLKIO_GETBLKSIZE: + *arg_size = dd->block_size; + break; + + case RTEMS_BLKIO_SETBLKSIZE: + dd->block_size = *arg_size; + break; + + case RTEMS_BLKIO_GETSIZE: + *arg_size = dd->size; + break; + + default: + errno = EINVAL; + return -1; + break; + } + + rtems_disk_release(dd); + + return 0; +} diff --git a/cpukit/libblock/src/flashdisk.c b/cpukit/libblock/src/flashdisk.c index 879ee9d61c..56077f4d45 100644 --- a/cpukit/libblock/src/flashdisk.c +++ b/cpukit/libblock/src/flashdisk.c @@ -2410,7 +2410,7 @@ rtems_fdisk_ioctl (dev_t dev, uint32_t req, void* argp) break; default: - errno = EINVAL; + return rtems_blkdev_ioctl (dev, req, argp); break; } diff --git a/cpukit/libblock/src/nvdisk.c b/cpukit/libblock/src/nvdisk.c index 7157dd08ab..3776e92d29 100644 --- a/cpukit/libblock/src/nvdisk.c +++ b/cpukit/libblock/src/nvdisk.c @@ -744,7 +744,7 @@ rtems_nvdisk_ioctl (dev_t dev, uint32_t req, void* argp) break; default: - errno = EINVAL; + return rtems_blkdev_ioctl (dev, req, argp); break; } diff --git a/cpukit/libblock/src/ramdisk.c b/cpukit/libblock/src/ramdisk.c index b2c802deee..faa5fef57b 100644 --- a/cpukit/libblock/src/ramdisk.c +++ b/cpukit/libblock/src/ramdisk.c @@ -206,11 +206,14 @@ ramdisk_ioctl(dev_t dev, uint32_t req, void *argp) } break; } - + default: - errno = EINVAL; - return -1; + return rtems_blkdev_ioctl (dev, req, argp); + break; } + + errno = EINVAL; + return -1; } /* ramdisk_initialize -- -- cgit v1.2.3