summaryrefslogtreecommitdiffstats
path: root/cpukit/libblock/src/flashdisk.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libblock/src/flashdisk.c')
-rw-r--r--cpukit/libblock/src/flashdisk.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/cpukit/libblock/src/flashdisk.c b/cpukit/libblock/src/flashdisk.c
index 87e9e53e97..b778ab5a19 100644
--- a/cpukit/libblock/src/flashdisk.c
+++ b/cpukit/libblock/src/flashdisk.c
@@ -177,6 +177,7 @@ typedef struct rtems_flashdisk
mappings. */
uint32_t block_count; /**< The number of avail. blocks. */
uint32_t unavail_blocks; /**< The number of unavail blocks. */
+ uint32_t starvation_threshold; /**< Erased blocks starvation threshold. */
uint32_t erased_blocks; /**< The number of erased blocks. */
rtems_fdisk_device_ctl* devices; /**< The flash devices for this
@@ -280,7 +281,7 @@ rtems_fdisk_printf (const rtems_flashdisk* fd, const char *format, ...)
static bool
rtems_fdisk_is_erased_blocks_starvation (rtems_flashdisk* fd)
{
- bool starvation = fd->erased_blocks < fd->unavail_blocks;
+ bool starvation = fd->erased_blocks < fd->starvation_threshold;
if (starvation)
fd->starvations++;
@@ -1260,12 +1261,18 @@ rtems_fdisk_recycle_segment (rtems_flashdisk* fd,
for (spage = 0; spage < ssc->pages; spage++)
{
- uint32_t dst_pages;
rtems_fdisk_page_desc* spd = &ssc->page_descriptors[spage];
+ if (!dsc && ssc->pages_active > 0)
+ {
+ rtems_fdisk_error ("recycle: no available dst segment");
+ return EIO;
+ }
+
if (rtems_fdisk_page_desc_flags_set (spd, RTEMS_FDISK_PAGE_ACTIVE) &&
!rtems_fdisk_page_desc_flags_set (spd, RTEMS_FDISK_PAGE_USED))
{
+ uint32_t dst_pages;
rtems_fdisk_page_desc* dpd;
uint32_t dpage;
@@ -1351,14 +1358,7 @@ rtems_fdisk_recycle_segment (rtems_flashdisk* fd,
*/
dst_pages = rtems_fdisk_seg_pages_available (dsc);
if (dst_pages == 0)
- {
dsc = rtems_fdisk_seg_most_available (&fd->available);
- if (!dsc)
- {
- rtems_fdisk_error ("recycle: no available dst segment");
- return EIO;
- }
- }
(*pages)--;
}
@@ -1405,6 +1405,10 @@ rtems_fdisk_compact (rtems_flashdisk* fd)
if (rtems_fdisk_is_erased_blocks_starvation (fd))
{
+#if RTEMS_FDISK_TRACE
+ rtems_fdisk_printf (fd, " resolve starvation");
+#endif
+
ssc = rtems_fdisk_segment_queue_pop_head (&fd->used);
if (!ssc)
ssc = rtems_fdisk_segment_queue_pop_head (&fd->available);
@@ -1482,7 +1486,12 @@ rtems_fdisk_compact (rtems_flashdisk* fd)
*/
if (!ssc || (pages == 0) || ((compacted_segs + segments) == 1))
+ {
+#if RTEMS_FDISK_TRACE
+ rtems_fdisk_printf (fd, " nothing to compact");
+#endif
break;
+ }
#if RTEMS_FDISK_TRACE
rtems_fdisk_printf (fd, " ssc scan: %d-%d: p=%ld, seg=%ld",
@@ -1539,6 +1548,7 @@ rtems_fdisk_recover_block_mappings (rtems_flashdisk* fd)
* Scan each segment or each device recovering the valid pages.
*/
fd->erased_blocks = 0;
+ fd->starvation_threshold = 0;
for (device = 0; device < fd->device_count; device++)
{
uint32_t segment;
@@ -1557,6 +1567,8 @@ rtems_fdisk_recover_block_mappings (rtems_flashdisk* fd)
sc->pages_desc = rtems_fdisk_page_desc_pages (sd, fd->block_size);
sc->pages =
rtems_fdisk_pages_in_segment (sd, fd->block_size) - sc->pages_desc;
+ if (sc->pages > fd->starvation_threshold)
+ fd->starvation_threshold = sc->pages;
sc->pages_active = 0;
sc->pages_used = 0;
@@ -2225,6 +2237,7 @@ rtems_fdisk_print_status (rtems_flashdisk* fd)
rtems_fdisk_printf (fd, "Block count\t%d", fd->block_count);
rtems_fdisk_printf (fd, "Unavail blocks\t%d", fd->unavail_blocks);
+ rtems_fdisk_printf (fd, "Starvation threshold\t%d", fd->starvation_threshold);
rtems_fdisk_printf (fd, "Starvations\t%d", fd->starvations);
count = rtems_fdisk_segment_count_queue (&fd->available);
total = count;