summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-10-26 21:31:45 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-10-26 22:03:22 +0200
commit9dffa384e1ce14ab110a30737051c4e8c98d7fc3 (patch)
treeb0e9c4143e20c18d5a4742700157eca6dd64636d
parentlibblock: ramdisk documentation (diff)
downloadrtems-9dffa384e1ce14ab110a30737051c4e8c98d7fc3.tar.bz2
libblock: rtems_bdbuf_set_block_size() API change
The set block size must synchronize and purge the disk to avoid an inconsistent cache state and data corruption. The synchronization is optional depending on the new sync parameter. In some contexts a synchronization must not be performed, e.g. during disk creation.
-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) {