summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorChristian Mauderer <christian.mauderer@embedded-brains.de>2021-01-19 15:33:35 +0100
committerChristian Mauderer <christian.mauderer@embedded-brains.de>2021-03-26 14:25:38 +0100
commit6ae79e6df6fbc89ffbd6badb3f84d6a2b513fe83 (patch)
tree370419dc3ec031519955f899069222fbd138b91b /cpukit
parentgen_uuid.c: Revert previous patch (597e4f476568a225d14dfaff02074cf269ad62ac) (diff)
downloadrtems-6ae79e6df6fbc89ffbd6badb3f84d6a2b513fe83.tar.bz2
libblock: Add rtems_bdbuf_peek()
Adds a peek function that allows (for example) a file system to suggest the next blocks that should be used for read ahead. This can increase the read speed of fragmented files. Update #3689
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/include/rtems/bdbuf.h23
-rw-r--r--cpukit/include/rtems/diskdevs.h24
-rw-r--r--cpukit/libblock/src/bdbuf.c84
-rw-r--r--cpukit/libblock/src/blkdev-print-stats.c2
4 files changed, 109 insertions, 24 deletions
diff --git a/cpukit/include/rtems/bdbuf.h b/cpukit/include/rtems/bdbuf.h
index fbb4fc05e9..4d11a47619 100644
--- a/cpukit/include/rtems/bdbuf.h
+++ b/cpukit/include/rtems/bdbuf.h
@@ -540,6 +540,29 @@ rtems_bdbuf_read (
);
/**
+ * @brief Give a hint which blocks should be cached next.
+ *
+ * Provide a hint to the read ahead mechanism which blocks should be cached
+ * next. This overwrites the default linear pattern. You should use it in (for
+ * example) a file system to tell bdbuf where the next part of a fragmented file
+ * is. If you know the length of the file, you can provide that too.
+ *
+ * Before you can use this function, the rtems_bdbuf_init() routine must be
+ * called at least once to initialize everything. Otherwise you might get
+ * unexpected results.
+ *
+ * @param dd [in] The disk device.
+ * @param block [in] Linear media block number.
+ * @param nr_blocks [in] Number of consecutive blocks that can be pre-fetched.
+ */
+void
+rtems_bdbuf_peek (
+ rtems_disk_device *dd,
+ rtems_blkdev_bnum block,
+ uint32_t nr_blocks
+);
+
+/**
* Release the buffer obtained by a read call back to the cache. If the buffer
* was obtained by a get call and was not already in the cache the release
* modified call should be used. A buffer released with this call obtained by a
diff --git a/cpukit/include/rtems/diskdevs.h b/cpukit/include/rtems/diskdevs.h
index 85d157dcd5..527a8cc955 100644
--- a/cpukit/include/rtems/diskdevs.h
+++ b/cpukit/include/rtems/diskdevs.h
@@ -59,6 +59,11 @@ typedef int (*rtems_block_device_ioctl)(
#define RTEMS_DISK_READ_AHEAD_NO_TRIGGER ((rtems_blkdev_bnum) -1)
/**
+ * @brief Size value to set number of blocks based on config and disk size.
+ */
+#define RTEMS_DISK_READ_AHEAD_SIZE_AUTO (0)
+
+/**
* @brief Block device read-ahead control.
*/
typedef struct {
@@ -71,7 +76,8 @@ typedef struct {
* @brief Block value to trigger the read-ahead request.
*
* A value of @ref RTEMS_DISK_READ_AHEAD_NO_TRIGGER will disable further
- * read-ahead requests since no valid block can have this value.
+ * read-ahead requests (except the ones triggered by @a rtems_bdbuf_peek)
+ * since no valid block can have this value.
*/
rtems_blkdev_bnum trigger;
@@ -82,6 +88,14 @@ typedef struct {
* be arbitrary.
*/
rtems_blkdev_bnum next;
+
+ /**
+ * @brief Size of the next read-ahead request in blocks.
+ *
+ * A value of @ref RTEMS_DISK_READ_AHEAD_SIZE_AUTO will try to read the rest
+ * of the disk but at most the configured max_read_ahead_blocks.
+ */
+ uint32_t nr_blocks;
} rtems_blkdev_read_ahead;
/**
@@ -110,11 +124,17 @@ typedef struct {
/**
* @brief Read-ahead transfer count.
*
- * Each read-ahead transfer may read multiple blocks.
+ * Each read-ahead transfer may read multiple blocks. This counts all
+ * transfers (including peeks).
*/
uint32_t read_ahead_transfers;
/**
+ * @brief Read-ahead transfers caused by a peek.
+ */
+ uint32_t read_ahead_peeks;
+
+ /**
* @brief Count of blocks transfered from the device.
*/
uint32_t read_blocks;
diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c
index a7d471507c..8aadf9c8ae 100644
--- a/cpukit/libblock/src/bdbuf.c
+++ b/cpukit/libblock/src/bdbuf.c
@@ -2019,6 +2019,23 @@ rtems_bdbuf_read_ahead_reset (rtems_disk_device *dd)
}
static void
+rtems_bdbuf_read_ahead_add_to_chain (rtems_disk_device *dd)
+{
+ rtems_status_code sc;
+ rtems_chain_control *chain = &bdbuf_cache.read_ahead_chain;
+
+ if (rtems_chain_is_empty (chain))
+ {
+ sc = rtems_event_send (bdbuf_cache.read_ahead_task,
+ RTEMS_BDBUF_READ_AHEAD_WAKE_UP);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_RA_WAKE_UP);
+ }
+
+ rtems_chain_append_unprotected (chain, &dd->read_ahead.node);
+}
+
+static void
rtems_bdbuf_check_read_ahead_trigger (rtems_disk_device *dd,
rtems_blkdev_bnum block)
{
@@ -2026,18 +2043,8 @@ rtems_bdbuf_check_read_ahead_trigger (rtems_disk_device *dd,
&& dd->read_ahead.trigger == block
&& !rtems_bdbuf_is_read_ahead_active (dd))
{
- rtems_status_code sc;
- rtems_chain_control *chain = &bdbuf_cache.read_ahead_chain;
-
- if (rtems_chain_is_empty (chain))
- {
- sc = rtems_event_send (bdbuf_cache.read_ahead_task,
- RTEMS_BDBUF_READ_AHEAD_WAKE_UP);
- if (sc != RTEMS_SUCCESSFUL)
- rtems_bdbuf_fatal (RTEMS_BDBUF_FATAL_RA_WAKE_UP);
- }
-
- rtems_chain_append_unprotected (chain, &dd->read_ahead.node);
+ dd->read_ahead.nr_blocks = RTEMS_DISK_READ_AHEAD_SIZE_AUTO;
+ rtems_bdbuf_read_ahead_add_to_chain(dd);
}
}
@@ -2112,6 +2119,24 @@ rtems_bdbuf_read (rtems_disk_device *dd,
return sc;
}
+void
+rtems_bdbuf_peek (rtems_disk_device *dd,
+ rtems_blkdev_bnum block,
+ uint32_t nr_blocks)
+{
+ rtems_bdbuf_lock_cache ();
+
+ if (bdbuf_cache.read_ahead_enabled && nr_blocks > 0)
+ {
+ rtems_bdbuf_read_ahead_reset(dd);
+ dd->read_ahead.next = block;
+ dd->read_ahead.nr_blocks = nr_blocks;
+ rtems_bdbuf_read_ahead_add_to_chain(dd);
+ }
+
+ rtems_bdbuf_unlock_cache ();
+}
+
static rtems_status_code
rtems_bdbuf_check_bd_and_lock_cache (rtems_bdbuf_buffer *bd, const char *kind)
{
@@ -2952,18 +2977,33 @@ rtems_bdbuf_read_ahead_task (rtems_task_argument arg)
if (bd != NULL)
{
- uint32_t transfer_count = dd->block_count - block;
+ uint32_t transfer_count = dd->read_ahead.nr_blocks;
+ uint32_t blocks_until_end_of_disk = dd->block_count - block;
uint32_t max_transfer_count = bdbuf_config.max_read_ahead_blocks;
- if (transfer_count >= max_transfer_count)
- {
- transfer_count = max_transfer_count;
- dd->read_ahead.trigger = block + transfer_count / 2;
- dd->read_ahead.next = block + transfer_count;
- }
- else
- {
- dd->read_ahead.trigger = RTEMS_DISK_READ_AHEAD_NO_TRIGGER;
+ if (transfer_count == RTEMS_DISK_READ_AHEAD_SIZE_AUTO) {
+ transfer_count = blocks_until_end_of_disk;
+
+ if (transfer_count >= max_transfer_count)
+ {
+ transfer_count = max_transfer_count;
+ dd->read_ahead.trigger = block + transfer_count / 2;
+ dd->read_ahead.next = block + transfer_count;
+ }
+ else
+ {
+ dd->read_ahead.trigger = RTEMS_DISK_READ_AHEAD_NO_TRIGGER;
+ }
+ } else {
+ if (transfer_count > blocks_until_end_of_disk) {
+ transfer_count = blocks_until_end_of_disk;
+ }
+
+ if (transfer_count > max_transfer_count) {
+ transfer_count = max_transfer_count;
+ }
+
+ ++dd->stats.read_ahead_peeks;
}
++dd->stats.read_ahead_transfers;
diff --git a/cpukit/libblock/src/blkdev-print-stats.c b/cpukit/libblock/src/blkdev-print-stats.c
index 8edf24fd8c..539ff08157 100644
--- a/cpukit/libblock/src/blkdev-print-stats.c
+++ b/cpukit/libblock/src/blkdev-print-stats.c
@@ -47,6 +47,7 @@ void rtems_blkdev_print_stats(
" READ HITS | %" PRIu32 "\n"
" READ MISSES | %" PRIu32 "\n"
" READ AHEAD TRANSFERS | %" PRIu32 "\n"
+ " READ AHEAD PEEKS | %" PRIu32 "\n"
" READ BLOCKS | %" PRIu32 "\n"
" READ ERRORS | %" PRIu32 "\n"
" WRITE TRANSFERS | %" PRIu32 "\n"
@@ -59,6 +60,7 @@ void rtems_blkdev_print_stats(
stats->read_hits,
stats->read_misses,
stats->read_ahead_transfers,
+ stats->read_ahead_peeks,
stats->read_blocks,
stats->read_errors,
stats->write_transfers,