summaryrefslogtreecommitdiffstats
path: root/cpukit/libblock
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 /cpukit/libblock
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.
Diffstat (limited to 'cpukit/libblock')
-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
4 files changed, 28 insertions, 9 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;
}