[PATCH 4/4] libblock: Add rtems_bdbuf_set_block_size()
sebastian.huber at embedded-brains.de
sebastian.huber at embedded-brains.de
Wed Mar 28 13:30:28 UTC 2012
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;
--
1.6.4.2
More information about the devel
mailing list