summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/libblock/include/rtems/bdbuf.h18
-rw-r--r--cpukit/libblock/src/bdbuf.c13
-rw-r--r--cpukit/libblock/src/blkdev-ioctl.c2
-rw-r--r--cpukit/libblock/src/diskdevs-init.c4
-rw-r--r--testsuites/libtests/block15/init.c2
-rw-r--r--testsuites/libtests/block16/init.c2
6 files changed, 30 insertions, 11 deletions
diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h
index 05e324c342..8a4631b9db 100644
--- a/cpukit/libblock/include/rtems/bdbuf.h
+++ b/cpukit/libblock/include/rtems/bdbuf.h
@@ -644,21 +644,31 @@ rtems_bdbuf_purge_dev (rtems_disk_device *dd);
/**
* @brief Sets the block size of a disk device.
*
- * This will set the block size derived fields of the disk device. The
- * read-ahead state of this device is reset.
+ * This will set the block size derived fields of the disk device. If
+ * requested the disk device is synchronized before the block size change
+ * occurs. Since the cache is unlocked during the synchronization operation
+ * some tasks may access the disk device in the meantime. This may result in
+ * loss of data. After the synchronization the disk device is purged to ensure
+ * a consistent cache state and the block size change occurs. This also resets
+ * the read-ahead state of this disk device. Due to the purge operation this
+ * may result in loss of data.
*
* 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.
+ * @param block_size [in] The new block size.
+ * @param sync [in] If @c true, then synchronize the disk device before the
+ * block size change.
*
* @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);
+rtems_bdbuf_set_block_size (rtems_disk_device *dd,
+ uint32_t block_size,
+ bool sync);
/**
* @brief Returns the block device statistics.
diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c
index 3f4915be43..c4336cd8cd 100644
--- a/cpukit/libblock/src/bdbuf.c
+++ b/cpukit/libblock/src/bdbuf.c
@@ -2948,10 +2948,19 @@ rtems_bdbuf_purge_dev (rtems_disk_device *dd)
}
rtems_status_code
-rtems_bdbuf_set_block_size (rtems_disk_device *dd, uint32_t block_size)
+rtems_bdbuf_set_block_size (rtems_disk_device *dd,
+ uint32_t block_size,
+ bool sync)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
+ /*
+ * We do not care about the synchronization status since we will purge the
+ * device later.
+ */
+ if (sync)
+ rtems_bdbuf_syncdev (dd);
+
rtems_bdbuf_lock_cache ();
if (block_size > 0)
@@ -2978,7 +2987,7 @@ rtems_bdbuf_set_block_size (rtems_disk_device *dd, uint32_t block_size)
dd->block_to_media_block_shift = block_to_media_block_shift;
dd->bds_per_group = bds_per_group;
- rtems_bdbuf_read_ahead_reset (dd);
+ rtems_bdbuf_purge_dev (dd);
}
else
{
diff --git a/cpukit/libblock/src/blkdev-ioctl.c b/cpukit/libblock/src/blkdev-ioctl.c
index b2215f17c2..54360b3bec 100644
--- a/cpukit/libblock/src/blkdev-ioctl.c
+++ b/cpukit/libblock/src/blkdev-ioctl.c
@@ -37,7 +37,7 @@ rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp)
break;
case RTEMS_BLKIO_SETBLKSIZE:
- sc = rtems_bdbuf_set_block_size(dd, *(uint32_t *) argp);
+ sc = rtems_bdbuf_set_block_size(dd, *(uint32_t *) argp, true);
if (sc != RTEMS_SUCCESSFUL) {
errno = EIO;
rc = -1;
diff --git a/cpukit/libblock/src/diskdevs-init.c b/cpukit/libblock/src/diskdevs-init.c
index 5ec96b250c..02ef392a28 100644
--- a/cpukit/libblock/src/diskdevs-init.c
+++ b/cpukit/libblock/src/diskdevs-init.c
@@ -43,7 +43,7 @@ rtems_status_code rtems_disk_init_phys(
dd->capabilities = 0;
}
- sc = rtems_bdbuf_set_block_size(dd, block_size);
+ sc = rtems_bdbuf_set_block_size(dd, block_size, false);
} else {
sc = RTEMS_INVALID_NUMBER;
}
@@ -78,7 +78,7 @@ rtems_status_code rtems_disk_init_log(
&& block_count > 0
&& block_count <= phys_block_count - block_begin
) {
- sc = rtems_bdbuf_set_block_size(dd, phys_dd->media_block_size);
+ sc = rtems_bdbuf_set_block_size(dd, phys_dd->media_block_size, false);
} else {
sc = RTEMS_INVALID_NUMBER;
}
diff --git a/testsuites/libtests/block15/init.c b/testsuites/libtests/block15/init.c
index 3cefd6c0d8..e6de9c3d05 100644
--- a/testsuites/libtests/block15/init.c
+++ b/testsuites/libtests/block15/init.c
@@ -100,7 +100,7 @@ static void test_write_requests(rtems_disk_device *dd)
rtems_status_code sc;
int i;
- sc = rtems_bdbuf_set_block_size(dd, BLOCK_SIZE);
+ sc = rtems_bdbuf_set_block_size(dd, BLOCK_SIZE, true);
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
for (i = 0; i < ACTION_COUNT; ++i) {
diff --git a/testsuites/libtests/block16/init.c b/testsuites/libtests/block16/init.c
index e115227f8e..5c7033ff3d 100644
--- a/testsuites/libtests/block16/init.c
+++ b/testsuites/libtests/block16/init.c
@@ -92,7 +92,7 @@ static void test(void)
rtems_test_assert(media_bd [i]->buffer [0] == buf [i] + media_block_count);
}
- sc = rtems_bdbuf_set_block_size(dd, media_size);
+ sc = rtems_bdbuf_set_block_size(dd, media_size, true);
ASSERT_SC(sc);
for (i = 0; i < media_block_count; i += 2) {