[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