From 73c09b3b8efc52831e80295e010fd7bfbd8c4b0c Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 30 May 2012 13:40:34 +0200 Subject: libblock: Simplify disk management Add block_count and media_blocks_per_block to rtems_disk_device. Add and use rtems_disk_init_phys() and rtems_disk_init_log(). --- cpukit/libblock/Makefile.am | 1 + cpukit/libblock/include/rtems/bdbuf.h | 11 ++-- cpukit/libblock/include/rtems/diskdevs.h | 54 ++++++++++++++++---- cpukit/libblock/src/bdbuf.c | 27 ++++++---- cpukit/libblock/src/blkdev-imfs.c | 83 +++++++++++++----------------- cpukit/libblock/src/diskdevs-init.c | 88 ++++++++++++++++++++++++++++++++ cpukit/libblock/src/diskdevs.c | 83 +++++++++++++++--------------- testsuites/libtests/block01/init.c | 2 +- 8 files changed, 230 insertions(+), 119 deletions(-) create mode 100644 cpukit/libblock/src/diskdevs-init.c diff --git a/cpukit/libblock/Makefile.am b/cpukit/libblock/Makefile.am index 242c44e1f6..6ddc52418d 100644 --- a/cpukit/libblock/Makefile.am +++ b/cpukit/libblock/Makefile.am @@ -8,6 +8,7 @@ libblock_a_SOURCES = src/bdbuf.c \ src/blkdev-ioctl.c \ src/blkdev-ops.c \ src/diskdevs.c \ + src/diskdevs-init.c \ src/flashdisk.c \ src/ramdisk-driver.c \ src/ramdisk-init.c \ diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h index c065f4ec55..43a95dfe99 100644 --- a/cpukit/libblock/include/rtems/bdbuf.h +++ b/cpukit/libblock/include/rtems/bdbuf.h @@ -141,7 +141,7 @@ extern "C" { * A block being accessed is given to the file system layer and not accessible * to another requester until released back to the cache. The same goes to a * buffer in the transfer state. The transfer state means being read or - * written. If the file system has modifed the block and releases it as + * written. If the file system has modified the block and releases it as * modified it placed on the cache's modified list and a hold timer * initialised. The buffer is held for the hold time before being written to * disk. Buffers are held for a configurable period of time on the modified @@ -462,7 +462,7 @@ rtems_bdbuf_init (void); /** * Get block buffer for data to be written into. The buffers is set to the - * access or modifed access state. If the buffer is in the cache and modified + * access or modified access state. If the buffer is in the cache and modified * the state is access modified else the state is access. This buffer contents * are not initialised if the buffer is not already in the cache. If the block * is already resident in memory it is returned how-ever if not in memory the @@ -498,7 +498,7 @@ rtems_bdbuf_get ( /** * Get the block buffer and if not already in the cache read from the disk. If * specified block already cached return. The buffer is set to the access or - * modifed access state. If the buffer is in the cache and modified the state + * modified access state. If the buffer is in the cache and modified the state * is access modified else the state is access. If block is already being read * from disk for being written to disk this call blocks. If the buffer is * waiting to be written it is removed from modified queue and returned to the @@ -601,7 +601,7 @@ rtems_bdbuf_sync (rtems_bdbuf_buffer* bd); /** * Synchronize all modified buffers for this device with the disk and wait * until the transfers have completed. The sync mutex for the cache is locked - * stopping the addition of any further modifed buffers. It is only the + * stopping the addition of any further modified buffers. It is only the * currently modified buffers that are written. * * @note Nesting calls to sync multiple devices will be handled sequentially. A @@ -635,8 +635,7 @@ rtems_bdbuf_purge_dev (rtems_disk_device *dd); /** * @brief Sets the block size of a disk device. * - * This will also change the block_to_media_block_shift and bds_per_group - * fields of the disk device. + * This will set the block size derived fields of the disk device. * * Before you can use this function, the rtems_bdbuf_init() routine must be * called at least once to initialize the cache, otherwise a fatal error will diff --git a/cpukit/libblock/include/rtems/diskdevs.h b/cpukit/libblock/include/rtems/diskdevs.h index 2e3f7533f3..fe931f8a94 100644 --- a/cpukit/libblock/include/rtems/diskdevs.h +++ b/cpukit/libblock/include/rtems/diskdevs.h @@ -92,33 +92,48 @@ struct rtems_disk_device { unsigned uses; /** - * @brief Start block number. + * @brief Start media block number. * - * Equals zero for physical devices. It is a block offset to the related - * physical device for logical device. + * Equals zero for physical devices. It is a media block offset to the + * related physical device for logical device. */ rtems_blkdev_bnum start; /** - * @brief Size of the physical or logical disk in blocks. + * @brief Size of the physical or logical disk in media blocks. */ rtems_blkdev_bnum size; /** - * @brief Device block size in bytes. + * @brief Media block size in bytes. * - * This is the minimum transfer unit. It must be positive. + * This is the media transfer unit the hardware defaults to. + */ + uint32_t media_block_size; + + /** + * @brief Block size in bytes. + * + * This is the minimum transfer unit. It may be a multiple of the media + * block size. It must be positive. * * @see rtems_bdbuf_set_block_size(). */ uint32_t block_size; /** - * @brief Device media block size in bytes. + * @brief Block count. * - * This is the media transfer unit the hardware defaults to. + * @see rtems_bdbuf_set_block_size(). */ - uint32_t media_block_size; + rtems_blkdev_bnum block_count; + + /** + * @brief Media blocks per device blocks. + * + * @see rtems_bdbuf_set_block_size(). + */ + uint32_t media_blocks_per_block; /** * @brief Block to media block shift. @@ -259,7 +274,7 @@ 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 begin_block. The block count of the logcal disk will be + * disk device is @a block_begin. 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 @@ -278,7 +293,7 @@ rtems_status_code rtems_disk_create_phys( rtems_status_code rtems_disk_create_log( dev_t dev, dev_t phys, - rtems_blkdev_bnum begin_block, + rtems_blkdev_bnum block_begin, rtems_blkdev_bnum block_count, const char *name ); @@ -373,6 +388,23 @@ rtems_status_code rtems_disk_io_done(void); */ rtems_disk_device *rtems_disk_next(dev_t dev); +/* Internal function, do not use */ +rtems_status_code rtems_disk_init_phys( + rtems_disk_device *dd, + uint32_t block_size, + rtems_blkdev_bnum block_count, + rtems_block_device_ioctl handler, + void *driver_data +); + +/* Internal function, do not use */ +rtems_status_code rtems_disk_init_log( + rtems_disk_device *dd, + rtems_disk_device *phys_dd, + rtems_blkdev_bnum block_begin, + rtems_blkdev_bnum block_count +); + #ifdef __cplusplus } #endif diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c index 4985dc1e16..c0744c6db2 100644 --- a/cpukit/libblock/src/bdbuf.c +++ b/cpukit/libblock/src/bdbuf.c @@ -1754,20 +1754,23 @@ rtems_bdbuf_get_media_block (const rtems_disk_device *dd, rtems_blkdev_bnum block, rtems_blkdev_bnum *media_block_ptr) { - /* - * Compute the media block number. Drivers work with media block number not - * the block number a BD may have as this depends on the block size set by - * the user. - */ - rtems_blkdev_bnum mb = rtems_bdbuf_media_block (dd, block); - if (mb >= dd->size) + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (block < dd->block_count) + { + /* + * Compute the media block number. Drivers work with media block number not + * the block number a BD may have as this depends on the block size set by + * the user. + */ + *media_block_ptr = rtems_bdbuf_media_block (dd, block) + dd->start; + } + else { - return RTEMS_INVALID_ID; + sc = RTEMS_INVALID_ID; } - *media_block_ptr = mb + dd->start; - - return RTEMS_SUCCESSFUL; + return sc; } rtems_status_code @@ -2909,6 +2912,8 @@ rtems_bdbuf_set_block_size (rtems_disk_device *dd, uint32_t block_size) block_to_media_block_shift = -1; dd->block_size = block_size; + dd->block_count = dd->size / media_blocks_per_block; + dd->media_blocks_per_block = media_blocks_per_block; dd->block_to_media_block_shift = block_to_media_block_shift; dd->bds_per_group = bds_per_group; } diff --git a/cpukit/libblock/src/blkdev-imfs.c b/cpukit/libblock/src/blkdev-imfs.c index c159ca3abe..e3c76a1d2f 100644 --- a/cpukit/libblock/src/blkdev-imfs.c +++ b/cpukit/libblock/src/blkdev-imfs.c @@ -269,46 +269,36 @@ rtems_status_code rtems_blkdev_create( ) { rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_blkdev_imfs_context *ctx = malloc(sizeof(*ctx)); - if (block_count > 0) { - rtems_blkdev_imfs_context *ctx = calloc(1, sizeof(*ctx)); + if (ctx != NULL) { + sc = rtems_disk_init_phys( + &ctx->dd, + block_size, + block_count, + handler, + driver_data + ); - if (ctx != NULL) { - rtems_disk_device *dd = &ctx->dd; + ctx->fd = -1; - ctx->fd = -1; - - dd->phys_dev = dd; - dd->size = block_count; - dd->media_block_size = block_size; - dd->ioctl = handler; - dd->driver_data = driver_data; - - if ((*handler)(dd, RTEMS_BLKIO_CAPABILITIES, &dd->capabilities) != 0) { - dd->capabilities = 0; - } - - sc = rtems_bdbuf_set_block_size(dd, block_size); - if (sc == RTEMS_SUCCESSFUL) { - int rv = IMFS_make_generic_node( - device, - S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO, - &rtems_blkdev_imfs_control, - ctx - ); - - if (rv != 0) { - free(ctx); - sc = RTEMS_UNSATISFIED; - } - } else { + if (sc == RTEMS_SUCCESSFUL) { + int rv = IMFS_make_generic_node( + device, + S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO, + &rtems_blkdev_imfs_control, + ctx + ); + + if (rv != 0) { free(ctx); + sc = RTEMS_UNSATISFIED; } } else { - sc = RTEMS_NO_MEMORY; + free(ctx); } } else { - sc = RTEMS_INVALID_NUMBER; + sc = RTEMS_NO_MEMORY; } return sc; @@ -330,24 +320,21 @@ rtems_status_code rtems_blkdev_create_partition( rv = fstat(fd, &st); if (rv == 0 && S_ISBLK(st.st_mode)) { - rtems_disk_device *dd; + rtems_disk_device *phys_dd; - rv = rtems_disk_fd_get_disk_device(fd, &dd); + rv = rtems_disk_fd_get_disk_device(fd, &phys_dd); if (rv == 0) { - rtems_blkdev_bnum device_block_count = rtems_disk_get_block_count(dd); - - if ( - block_begin < device_block_count - && block_count > 0 - && block_count <= device_block_count - block_begin - ) { - rtems_blkdev_imfs_context *ctx = malloc(sizeof(*ctx)); + rtems_blkdev_imfs_context *ctx = malloc(sizeof(*ctx)); - if (ctx != NULL) { - memcpy(&ctx->dd, dd, sizeof(ctx->dd)); + if (ctx != NULL) { + sc = rtems_disk_init_log( + &ctx->dd, + phys_dd, + block_begin, + block_count + ); - ctx->dd.start = block_begin; - ctx->dd.size = block_count; + if (sc == RTEMS_SUCCESSFUL) { ctx->fd = fd; rv = IMFS_make_generic_node( @@ -362,10 +349,10 @@ rtems_status_code rtems_blkdev_create_partition( sc = RTEMS_UNSATISFIED; } } else { - sc = RTEMS_NO_MEMORY; + free(ctx); } } else { - sc = RTEMS_INVALID_NUMBER; + sc = RTEMS_NO_MEMORY; } } else { sc = RTEMS_NOT_IMPLEMENTED; diff --git a/cpukit/libblock/src/diskdevs-init.c b/cpukit/libblock/src/diskdevs-init.c new file mode 100644 index 0000000000..ccf954a49a --- /dev/null +++ b/cpukit/libblock/src/diskdevs-init.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include +#include + +rtems_status_code rtems_disk_init_phys( + rtems_disk_device *dd, + uint32_t block_size, + rtems_blkdev_bnum block_count, + rtems_block_device_ioctl handler, + void *driver_data +) +{ + rtems_status_code sc; + + dd = memset(dd, 0, sizeof(*dd)); + + dd->phys_dev = dd; + dd->size = block_count; + dd->media_block_size = block_size; + dd->ioctl = handler; + dd->driver_data = driver_data; + + if (block_count > 0) { + if ((*handler)(dd, RTEMS_BLKIO_CAPABILITIES, &dd->capabilities) != 0) { + dd->capabilities = 0; + } + + sc = rtems_bdbuf_set_block_size(dd, block_size); + } else { + sc = RTEMS_INVALID_NUMBER; + } + + return sc; +} + +rtems_status_code rtems_disk_init_log( + rtems_disk_device *dd, + rtems_disk_device *phys_dd, + rtems_blkdev_bnum block_begin, + rtems_blkdev_bnum block_count +) +{ + rtems_status_code sc; + + dd = memset(dd, 0, sizeof(*dd)); + + dd->phys_dev = phys_dd; + dd->start = block_begin; + dd->size = block_count; + dd->media_block_size = phys_dd->media_block_size; + dd->ioctl = phys_dd->ioctl; + dd->driver_data = phys_dd->driver_data; + + if (phys_dd->phys_dev == phys_dd) { + rtems_blkdev_bnum phys_block_count = phys_dd->size; + + if ( + block_begin < phys_block_count + && block_count > 0 + && block_count <= phys_block_count - block_begin + ) { + sc = rtems_bdbuf_set_block_size(dd, phys_dd->media_block_size); + } else { + sc = RTEMS_INVALID_NUMBER; + } + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} diff --git a/cpukit/libblock/src/diskdevs.c b/cpukit/libblock/src/diskdevs.c index 285bc05efb..96bcf88f52 100644 --- a/cpukit/libblock/src/diskdevs.c +++ b/cpukit/libblock/src/diskdevs.c @@ -10,7 +10,7 @@ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia * Author: Victor V. Vengerov * - * Copyright (c) 2009 embedded brains GmbH. + * Copyright (c) 2009-2012 embedded brains GmbH. */ #if HAVE_CONFIG_H @@ -170,7 +170,12 @@ create_disk_table_entry(dev_t dev) } static rtems_status_code -create_disk(dev_t dev, const char *name, rtems_disk_device **dd_ptr) +create_disk( + dev_t dev, + const char *name, + rtems_disk_device **dd_ptr, + char **alloc_name_ptr +) { rtems_disk_device **dd_entry = create_disk_table_entry(dev); rtems_disk_device *dd = NULL; @@ -207,13 +212,9 @@ create_disk(dev_t dev, const char *name, rtems_disk_device **dd_ptr) } } - dd->dev = dev; - dd->name = alloc_name; - dd->uses = 0; - dd->deleted = false; - *dd_entry = dd; *dd_ptr = dd; + *alloc_name_ptr = alloc_name; return RTEMS_SUCCESSFUL; } @@ -238,6 +239,7 @@ rtems_status_code rtems_disk_create_phys( { rtems_disk_device *dd = NULL; rtems_status_code sc = RTEMS_SUCCESSFUL; + char *alloc_name = NULL; if (handler == NULL) { return RTEMS_INVALID_ADDRESS; @@ -248,25 +250,24 @@ rtems_status_code rtems_disk_create_phys( return sc; } - sc = create_disk(dev, name, &dd); + sc = create_disk(dev, name, &dd, &alloc_name); if (sc != RTEMS_SUCCESSFUL) { disk_unlock(); return sc; } - dd->phys_dev = dd; - dd->start = 0; - dd->size = block_count; - dd->media_block_size = block_size; - dd->ioctl = handler; - dd->driver_data = driver_data; + sc = rtems_disk_init_phys( + dd, + block_size, + block_count, + handler, + driver_data + ); - if ((*handler)(dd, RTEMS_BLKIO_CAPABILITIES, &dd->capabilities) < 0) { - dd->capabilities = 0; - } + dd->dev = dev; + dd->name = alloc_name; - sc = rtems_bdbuf_set_block_size(dd, block_size); if (sc != RTEMS_SUCCESSFUL) { dd->ioctl = null_handler; rtems_disk_delete(dev); @@ -289,57 +290,55 @@ is_physical_disk(const rtems_disk_device *dd) rtems_status_code rtems_disk_create_log( dev_t dev, dev_t phys, - rtems_blkdev_bnum begin_block, + rtems_blkdev_bnum block_begin, rtems_blkdev_bnum block_count, const char *name ) { rtems_status_code sc = RTEMS_SUCCESSFUL; - rtems_disk_device *physical_disk = NULL; + rtems_disk_device *phys_dd = NULL; rtems_disk_device *dd = NULL; - rtems_blkdev_bnum end_block = begin_block + block_count; + char *alloc_name = NULL; sc = disk_lock(); if (sc != RTEMS_SUCCESSFUL) { return sc; } - physical_disk = get_disk_entry(phys, true); - if (physical_disk == NULL || !is_physical_disk(physical_disk)) { + phys_dd = get_disk_entry(phys, true); + if (phys_dd == NULL) { disk_unlock(); return RTEMS_INVALID_ID; } - if ( - begin_block >= physical_disk->size - || end_block <= begin_block - || end_block > physical_disk->size - ) { + sc = create_disk(dev, name, &dd, &alloc_name); + if (sc != RTEMS_SUCCESSFUL) { disk_unlock(); - return RTEMS_INVALID_NUMBER; + return sc; } - sc = create_disk(dev, name, &dd); + sc = rtems_disk_init_log( + dd, + phys_dd, + block_begin, + block_count + ); + + dd->dev = dev; + dd->name = alloc_name; + + ++phys_dd->uses; + if (sc != RTEMS_SUCCESSFUL) { + dd->ioctl = null_handler; + rtems_disk_delete(dev); disk_unlock(); return sc; } - dd->phys_dev = physical_disk; - dd->start = begin_block; - dd->size = block_count; - dd->block_size = physical_disk->block_size; - dd->media_block_size = physical_disk->media_block_size; - dd->block_to_media_block_shift = physical_disk->block_to_media_block_shift; - dd->bds_per_group = physical_disk->bds_per_group; - dd->ioctl = physical_disk->ioctl; - dd->driver_data = physical_disk->driver_data; - - ++physical_disk->uses; - disk_unlock(); return RTEMS_SUCCESSFUL; diff --git a/testsuites/libtests/block01/init.c b/testsuites/libtests/block01/init.c index 03ff097b62..c26f18adbd 100644 --- a/testsuites/libtests/block01/init.c +++ b/testsuites/libtests/block01/init.c @@ -183,7 +183,7 @@ static void test_diskdevs(void) sc = rtems_disk_create_log(logical_dev, physical_dev, 0, 1, "/dev/rda1"); ASSERT_SC_EQ(sc, RTEMS_RESOURCE_IN_USE); - sc = rtems_disk_create_log(logical_2_dev, logical_dev, 0, 1, "/dev/rda1"); + sc = rtems_disk_create_log(logical_2_dev, logical_dev, 0, 1, "/dev/rda2"); ASSERT_SC_EQ(sc, RTEMS_INVALID_ID); sc = rtems_disk_delete(logical_dev); -- cgit v1.2.3