[PATCH 4/4] libblock: Add rtems_bdbuf_set_block_size()
Chris Johns
chrisj at rtems.org
Thu Apr 12 03:11:32 UTC 2012
Looks fine.
On 29/03/12 12:30 AM, sebastian.huber at embedded-brains.de wrote:
> From: Sebastian Huber<sebastian.huber at embedded-brains.de>
>
> The new function rtems_bdbuf_set_block_size() must be used to set the
> block size of a disk device. It will check if the block size is valid
> and set the new fields block_to_media_block_shift and bds_per_group of
> the rtems_disk_device structure. This helps to avoid complex arithmetic
> operations in the block device buffer get and read path.
> ---
> cpukit/libblock/include/rtems/bdbuf.h | 15 ++++
> cpukit/libblock/include/rtems/diskdevs.h | 24 +++++-
> cpukit/libblock/src/bdbuf.c | 124 +++++++++++++++++------------
> cpukit/libblock/src/blkdev-imfs.c | 27 ++++---
> cpukit/libblock/src/blkdev-ioctl.c | 23 +++---
> cpukit/libblock/src/diskdevs.c | 29 ++++++--
> 6 files changed, 159 insertions(+), 83 deletions(-)
>
> diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h
> index c2fe0dd..cdac89d 100644
> --- a/cpukit/libblock/include/rtems/bdbuf.h
> +++ b/cpukit/libblock/include/rtems/bdbuf.h
> @@ -589,6 +589,21 @@ rtems_bdbuf_syncdev (const rtems_disk_device *dd);
> void
> rtems_bdbuf_purge_dev (const 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.
> + *
> + * @param dd [in, out] The disk device.
> + * @param dd [in] The new block size.
> + *
> + * @retval RTEMS_SUCCESSFUL Successful operation.
> + * @retval RTEMS_INVALID_NUMBER Invalid block size.
> + */
> +rtems_status_code
> +rtems_bdbuf_set_block_size (rtems_disk_device *dd, uint32_t block_size);
> +
> /** @} */
>
> #ifdef __cplusplus
> diff --git a/cpukit/libblock/include/rtems/diskdevs.h b/cpukit/libblock/include/rtems/diskdevs.h
> index 8e59f36..8571daa 100644
> --- a/cpukit/libblock/include/rtems/diskdevs.h
> +++ b/cpukit/libblock/include/rtems/diskdevs.h
> @@ -109,7 +109,9 @@ struct rtems_disk_device {
> /**
> * @brief Device block size in bytes.
> *
> - * This is the minimum transfer unit. It can be any size.
> + * This is the minimum transfer unit. It must be positive.
> + *
> + * @see rtems_bdbuf_set_block_size().
> */
> uint32_t block_size;
>
> @@ -121,6 +123,24 @@ struct rtems_disk_device {
> uint32_t media_block_size;
>
> /**
> + * @brief Block to media block shift.
> + *
> + * In case this value is non-negative the media block of a block can be
> + * calculated as media block = block<< block_to_media_block_shift, otherwise
> + * a 64-bit operation will be used.
> + *
> + * @see rtems_bdbuf_set_block_size().
> + */
> + int block_to_media_block_shift;
> +
> + /**
> + * @brief Buffer descriptors per group count.
> + *
> + * @see rtems_bdbuf_set_block_size().
> + */
> + size_t bds_per_group;
> +
> + /**
> * @brief IO control handler for this disk.
> */
> rtems_block_device_ioctl ioctl;
> @@ -222,7 +242,7 @@ static inline rtems_blkdev_bnum rtems_disk_get_block_count(
> * @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_INVALID_NUMBER Block size is invalid.
> * @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.
> diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c
> index bfbf9f0..f6d9327 100644
> --- a/cpukit/libblock/src/bdbuf.c
> +++ b/cpukit/libblock/src/bdbuf.c
> @@ -815,22 +815,18 @@ rtems_bdbuf_set_state (rtems_bdbuf_buffer *bd, rtems_bdbuf_buf_state state)
> bd->state = state;
> }
>
> -/**
> - * Change the block number for the block size to the block number for the media
> - * block size. We have to use 64bit maths. There is no short cut here.
> - *
> - * @param block The logical block number in the block size terms.
> - * @param block_size The block size.
> - * @param media_block_size The block size of the media.
> - * @return rtems_blkdev_bnum The media block number.
> - */
> static rtems_blkdev_bnum
> -rtems_bdbuf_media_block (rtems_blkdev_bnum block,
> - size_t block_size,
> - size_t media_block_size)
> +rtems_bdbuf_media_block (const rtems_disk_device *dd, rtems_blkdev_bnum block)
> {
> - return (rtems_blkdev_bnum)
> - ((((uint64_t) block) * block_size) / media_block_size);
> + if (dd->block_to_media_block_shift>= 0)
> + return block<< dd->block_to_media_block_shift;
> + else
> + /*
> + * Change the block number for the block size to the block number for the media
> + * block size. We have to use 64bit maths. There is no short cut here.
> + */
> + return (rtems_blkdev_bnum)
> + ((((uint64_t) block) * dd->block_size) / dd->media_block_size);
> }
>
> /**
> @@ -1736,40 +1732,22 @@ rtems_bdbuf_get_buffer_for_access (const rtems_disk_device *dd,
> }
>
> static rtems_status_code
> -rtems_bdbuf_obtain_disk (const rtems_disk_device *dd,
> - rtems_blkdev_bnum block,
> - rtems_blkdev_bnum *media_block_ptr,
> - size_t *bds_per_group_ptr)
> +rtems_bdbuf_get_media_block (const rtems_disk_device *dd,
> + rtems_blkdev_bnum block,
> + rtems_blkdev_bnum *media_block_ptr)
> {
> - if (media_block_ptr != NULL)
> + /*
> + * 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)
> {
> - /*
> - * 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 (block,
> - dd->block_size,
> - dd->media_block_size);
> - if (mb>= dd->size)
> - {
> - return RTEMS_INVALID_NUMBER;
> - }
> -
> - *media_block_ptr = mb + dd->start;
> + return RTEMS_INVALID_NUMBER;
> }
>
> - if (bds_per_group_ptr != NULL)
> - {
> - size_t bds_per_group = rtems_bdbuf_bds_per_group (dd->block_size);
> -
> - if (bds_per_group == 0)
> - {
> - return RTEMS_INVALID_NUMBER;
> - }
> -
> - *bds_per_group_ptr = bds_per_group;
> - }
> + *media_block_ptr = mb + dd->start;
>
> return RTEMS_SUCCESSFUL;
> }
> @@ -1782,9 +1760,8 @@ rtems_bdbuf_get (const rtems_disk_device *dd,
> rtems_status_code sc = RTEMS_SUCCESSFUL;
> rtems_bdbuf_buffer *bd = NULL;
> rtems_blkdev_bnum media_block = 0;
> - size_t bds_per_group = 0;
>
> - sc = rtems_bdbuf_obtain_disk (dd, block,&media_block,&bds_per_group);
> + sc = rtems_bdbuf_get_media_block (dd, block,&media_block);
> if (sc != RTEMS_SUCCESSFUL)
> return sc;
>
> @@ -1797,7 +1774,7 @@ rtems_bdbuf_get (const rtems_disk_device *dd,
> printf ("bdbuf:get: %" PRIu32 " (%" PRIu32 ") (dev = %08x)\n",
> media_block, block, (unsigned) dd->dev);
>
> - bd = rtems_bdbuf_get_buffer_for_access (dd, media_block, bds_per_group);
> + bd = rtems_bdbuf_get_buffer_for_access (dd, media_block, dd->bds_per_group);
>
> switch (bd->state)
> {
> @@ -1863,7 +1840,9 @@ rtems_bdbuf_create_read_request (const rtems_disk_device *dd,
> {
> rtems_bdbuf_buffer *bd = NULL;
> rtems_blkdev_bnum media_block_end = dd->start + dd->size;
> - rtems_blkdev_bnum media_block_count = dd->block_size / dd->media_block_size;
> + rtems_blkdev_bnum media_block_count = dd->block_to_media_block_shift>= 0 ?
> + dd->block_size>> dd->block_to_media_block_shift
> + : dd->block_size / dd->media_block_size;
> uint32_t block_size = dd->block_size;
> uint32_t transfer_index = 1;
> uint32_t transfer_count = bdbuf_config.max_read_ahead_blocks + 1;
> @@ -2000,9 +1979,8 @@ rtems_bdbuf_read (const rtems_disk_device *dd,
> rtems_blkdev_request *req = NULL;
> rtems_bdbuf_buffer *bd = NULL;
> rtems_blkdev_bnum media_block = 0;
> - size_t bds_per_group = 0;
>
> - sc = rtems_bdbuf_obtain_disk (dd, block,&media_block,&bds_per_group);
> + sc = rtems_bdbuf_get_media_block (dd, block,&media_block);
> if (sc != RTEMS_SUCCESSFUL)
> return sc;
>
> @@ -2020,7 +1998,7 @@ rtems_bdbuf_read (const rtems_disk_device *dd,
> media_block + dd->start, block, (unsigned) dd->dev);
>
> rtems_bdbuf_lock_cache ();
> - rtems_bdbuf_create_read_request (dd, media_block, bds_per_group, req,&bd);
> + rtems_bdbuf_create_read_request (dd, media_block, dd->bds_per_group, req,&bd);
>
> if (req->bufnum> 0)
> {
> @@ -2895,3 +2873,47 @@ rtems_bdbuf_purge_dev (const rtems_disk_device *dd)
> rtems_bdbuf_purge_list (&purge_list);
> rtems_bdbuf_unlock_cache ();
> }
> +
> +rtems_status_code
> +rtems_bdbuf_set_block_size (rtems_disk_device *dd, uint32_t block_size)
> +{
> + rtems_status_code sc = RTEMS_SUCCESSFUL;
> +
> + rtems_bdbuf_lock_cache ();
> +
> + if (block_size> 0)
> + {
> + size_t bds_per_group = rtems_bdbuf_bds_per_group (block_size);
> +
> + if (bds_per_group != 0)
> + {
> + int block_to_media_block_shift = 0;
> + uint32_t media_blocks_per_block = block_size / dd->media_block_size;
> + uint32_t one = 1;
> +
> + while ((one<< block_to_media_block_shift)< media_blocks_per_block)
> + {
> + ++block_to_media_block_shift;
> + }
> +
> + if ((dd->media_block_size<< block_to_media_block_shift) != block_size)
> + block_to_media_block_shift = -1;
> +
> + dd->block_size = block_size;
> + dd->block_to_media_block_shift = block_to_media_block_shift;
> + dd->bds_per_group = bds_per_group;
> + }
> + else
> + {
> + sc = RTEMS_INVALID_NUMBER;
> + }
> + }
> + else
> + {
> + sc = RTEMS_INVALID_NUMBER;
> + }
> +
> + rtems_bdbuf_unlock_cache ();
> +
> + return sc;
> +}
> diff --git a/cpukit/libblock/src/blkdev-imfs.c b/cpukit/libblock/src/blkdev-imfs.c
> index 080ca21..fe7a80c 100644
> --- a/cpukit/libblock/src/blkdev-imfs.c
> +++ b/cpukit/libblock/src/blkdev-imfs.c
> @@ -268,19 +268,17 @@ rtems_status_code rtems_blkdev_create(
> {
> rtems_status_code sc = RTEMS_SUCCESSFUL;
>
> - if (block_size> 0&& block_count> 0) {
> + if (block_count> 0) {
> rtems_blkdev_imfs_context *ctx = calloc(1, sizeof(*ctx));
>
> if (ctx != NULL) {
> rtems_disk_device *dd =&ctx->dd;
> - int rv;
>
> ctx->fd = -1;
>
> dd->phys_dev = dd;
> dd->size = block_count;
> dd->media_block_size = block_size;
> - dd->block_size = block_size;
> dd->ioctl = handler;
> dd->driver_data = driver_data;
>
> @@ -288,16 +286,21 @@ rtems_status_code rtems_blkdev_create(
> dd->capabilities = 0;
> }
>
> - rv = IMFS_make_generic_node(
> - device,
> - S_IFBLK | S_IRWXU | S_IRWXG | S_IRWXO,
> -&rtems_blkdev_imfs_control,
> - ctx
> - );
> -
> - if (rv != 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 {
> free(ctx);
> - sc = RTEMS_UNSATISFIED;
> }
> } else {
> sc = RTEMS_NO_MEMORY;
> diff --git a/cpukit/libblock/src/blkdev-ioctl.c b/cpukit/libblock/src/blkdev-ioctl.c
> index 296f379..52f19b5 100644
> --- a/cpukit/libblock/src/blkdev-ioctl.c
> +++ b/cpukit/libblock/src/blkdev-ioctl.c
> @@ -23,43 +23,42 @@
> int
> rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)
> {
> - size_t *arg_size = argp;
> + rtems_status_code sc;
> int rc = 0;
>
> switch (req)
> {
> case RTEMS_BLKIO_GETMEDIABLKSIZE:
> - *arg_size = dd->media_block_size;
> + *(uint32_t *) argp = dd->media_block_size;
> break;
>
> case RTEMS_BLKIO_GETBLKSIZE:
> - *arg_size = dd->block_size;
> + *(uint32_t *) argp = dd->block_size;
> break;
>
> case RTEMS_BLKIO_SETBLKSIZE:
> - dd->block_size = *arg_size;
> + sc = rtems_bdbuf_set_block_size(dd, *(uint32_t *) argp);
> + if (sc != RTEMS_SUCCESSFUL) {
> + errno = EIO;
> + rc = -1;
> + }
> break;
>
> case RTEMS_BLKIO_GETSIZE:
> - *arg_size = dd->size;
> + *(rtems_blkdev_bnum *) argp = dd->size;
> break;
>
> case RTEMS_BLKIO_SYNCDEV:
> - {
> - rtems_status_code sc = rtems_bdbuf_syncdev(dd);
> + sc = rtems_bdbuf_syncdev(dd);
> if (sc != RTEMS_SUCCESSFUL) {
> errno = EIO;
> rc = -1;
> }
> break;
> - }
>
> case RTEMS_BLKIO_GETDISKDEV:
> - {
> - rtems_disk_device **dd_ptr = argp;
> - *dd_ptr = dd;
> + *(rtems_disk_device **) argp = dd;
> break;
> - }
>
> default:
> errno = EINVAL;
> diff --git a/cpukit/libblock/src/diskdevs.c b/cpukit/libblock/src/diskdevs.c
> index 08a6a9b..500569f 100644
> --- a/cpukit/libblock/src/diskdevs.c
> +++ b/cpukit/libblock/src/diskdevs.c
> @@ -220,6 +220,15 @@ create_disk(dev_t dev, const char *name, rtems_disk_device **dd_ptr)
> return RTEMS_SUCCESSFUL;
> }
>
> +static int null_handler(
> + rtems_disk_device *dd,
> + uint32_t req,
> + void *argp
> +)
> +{
> + return -1;
> +}
> +
> rtems_status_code rtems_disk_create_phys(
> dev_t dev,
> uint32_t block_size,
> @@ -236,10 +245,6 @@ rtems_status_code rtems_disk_create_phys(
> return RTEMS_INVALID_ADDRESS;
> }
>
> - if (block_size == 0) {
> - return RTEMS_INVALID_NUMBER;
> - }
> -
> sc = disk_lock();
> if (sc != RTEMS_SUCCESSFUL) {
> return sc;
> @@ -255,7 +260,7 @@ rtems_status_code rtems_disk_create_phys(
> dd->phys_dev = dd;
> dd->start = 0;
> dd->size = block_count;
> - dd->block_size = dd->media_block_size = block_size;
> + dd->media_block_size = block_size;
> dd->ioctl = handler;
> dd->driver_data = driver_data;
>
> @@ -263,6 +268,15 @@ rtems_status_code rtems_disk_create_phys(
> dd->capabilities = 0;
> }
>
> + sc = rtems_bdbuf_set_block_size(dd, block_size);
> + if (sc != RTEMS_SUCCESSFUL) {
> + dd->ioctl = null_handler;
> + rtems_disk_delete(dev);
> + disk_unlock();
> +
> + return sc;
> + }
> +
> disk_unlock();
>
> return RTEMS_SUCCESSFUL;
> @@ -319,7 +333,10 @@ rtems_status_code rtems_disk_create_log(
> 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->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;
>
More information about the devel
mailing list