forked from Imagelibrary/rtems
libblock: Add rtems_bdbuf_set_block_size()
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.
This commit is contained in:
@@ -479,7 +479,7 @@ rtems_bdbuf_init (void);
|
||||
* @param bd [out] Reference to the buffer descriptor pointer.
|
||||
*
|
||||
* @retval RTEMS_SUCCESSFUL Successful operation.
|
||||
* @retval RTEMS_INVALID_NUMBER Invalid block size.
|
||||
* @retval RTEMS_INVALID_ID Invalid block number.
|
||||
*/
|
||||
rtems_status_code
|
||||
rtems_bdbuf_get (
|
||||
@@ -512,7 +512,7 @@ rtems_bdbuf_get (
|
||||
* @param bd [out] Reference to the buffer descriptor pointer.
|
||||
*
|
||||
* @retval RTEMS_SUCCESSFUL Successful operation.
|
||||
* @retval RTEMS_INVALID_NUMBER Invalid block size.
|
||||
* @retval RTEMS_INVALID_ID Invalid block number.
|
||||
* @retval RTEMS_IO_ERROR IO error.
|
||||
*/
|
||||
rtems_status_code
|
||||
@@ -625,6 +625,25 @@ 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.
|
||||
*
|
||||
* 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
|
||||
* occur.
|
||||
*
|
||||
* @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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -120,6 +122,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.
|
||||
*/
|
||||
@@ -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.
|
||||
|
||||
@@ -822,22 +822,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1743,40 +1739,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_ID;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1789,9 +1767,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;
|
||||
|
||||
@@ -1804,7 +1781,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)
|
||||
{
|
||||
@@ -1870,7 +1847,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;
|
||||
@@ -2007,9 +1986,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;
|
||||
|
||||
@@ -2027,7 +2005,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)
|
||||
{
|
||||
@@ -2902,3 +2880,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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
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) {
|
||||
if (rv != 0) {
|
||||
free(ctx);
|
||||
sc = RTEMS_UNSATISFIED;
|
||||
}
|
||||
} else {
|
||||
free(ctx);
|
||||
sc = RTEMS_UNSATISFIED;
|
||||
}
|
||||
} else {
|
||||
sc = RTEMS_NO_MEMORY;
|
||||
|
||||
@@ -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;
|
||||
break;
|
||||
|
||||
case RTEMS_BLKIO_GETSIZE:
|
||||
*arg_size = dd->size;
|
||||
break;
|
||||
|
||||
case RTEMS_BLKIO_SYNCDEV:
|
||||
{
|
||||
rtems_status_code sc = rtems_bdbuf_syncdev(dd);
|
||||
sc = rtems_bdbuf_set_block_size(dd, *(uint32_t *) argp);
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
errno = EIO;
|
||||
rc = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case RTEMS_BLKIO_GETSIZE:
|
||||
*(rtems_blkdev_bnum *) argp = dd->size;
|
||||
break;
|
||||
|
||||
case RTEMS_BLKIO_SYNCDEV:
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user