From 11db49e2d3b578576220ada57ff4c74128c19613 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 27 Sep 2023 00:32:13 +0300 Subject: [PATCH] Kernel: DiskCache now requires sync to be called from kernel thread This disables the scenario where user interrupts sync operation possibly leaving the syncing in invalid state. --- kernel/include/kernel/Storage/DiskCache.h | 1 + kernel/kernel/Storage/DiskCache.cpp | 54 +++++++++++++++-------- kernel/kernel/Storage/StorageDevice.cpp | 2 +- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/kernel/include/kernel/Storage/DiskCache.h b/kernel/include/kernel/Storage/DiskCache.h index 342a855a4a..99b88ce4c6 100644 --- a/kernel/include/kernel/Storage/DiskCache.h +++ b/kernel/include/kernel/Storage/DiskCache.h @@ -36,6 +36,7 @@ namespace Kernel const size_t m_sector_size; StorageDevice& m_device; BAN::Vector m_cache; + BAN::Array m_sync_cache; }; } \ No newline at end of file diff --git a/kernel/kernel/Storage/DiskCache.cpp b/kernel/kernel/Storage/DiskCache.cpp index 9307709ede..3ec008e0a6 100644 --- a/kernel/kernel/Storage/DiskCache.cpp +++ b/kernel/kernel/Storage/DiskCache.cpp @@ -118,30 +118,48 @@ namespace Kernel BAN::ErrorOr DiskCache::sync() { - BAN::Vector sector_buffer; - TRY(sector_buffer.resize(m_sector_size)); - - PageTable& page_table = PageTable::current(); - LockGuard page_table_locker(page_table); - ASSERT(page_table.is_page_free(0)); + ASSERT(&PageTable::current() == &PageTable::kernel()); + auto& page_table = PageTable::kernel(); for (auto& cache : m_cache) { - for (int i = 0; cache.dirty_mask; i++) + if (cache.dirty_mask == 0) + continue; + { - if (!(cache.dirty_mask & (1 << i))) - continue; + LockGuard _(page_table); + ASSERT(page_table.is_page_free(0)); - { - CriticalScope _; - page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present); - memcpy(sector_buffer.data(), (void*)(i * m_sector_size), m_sector_size); - page_table.unmap_page(0); - } - - TRY(m_device.write_sectors_impl(cache.first_sector + i, 1, sector_buffer.data())); - cache.dirty_mask &= ~(1 << i); + page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present); + memcpy(m_sync_cache.data(), (void*)0, PAGE_SIZE); + page_table.unmap_page(0); } + + uint8_t sector_start = 0; + uint8_t sector_count = 0; + + while (sector_start + sector_count <= PAGE_SIZE / m_sector_size) + { + if (cache.dirty_mask & (1 << (sector_start + sector_count))) + sector_count++; + else if (sector_count == 0) + sector_start++; + else + { + dprintln("syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count); + TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, m_sync_cache.data() + sector_start * m_sector_size)); + sector_start += sector_count + 1; + sector_count = 0; + } + } + + if (sector_count > 0) + { + dprintln("syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count); + TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, m_sync_cache.data() + sector_start * m_sector_size)); + } + + cache.dirty_mask = 0; } return {}; diff --git a/kernel/kernel/Storage/StorageDevice.cpp b/kernel/kernel/Storage/StorageDevice.cpp index 93070eab69..a545b7be47 100644 --- a/kernel/kernel/Storage/StorageDevice.cpp +++ b/kernel/kernel/Storage/StorageDevice.cpp @@ -260,7 +260,7 @@ namespace Kernel { LockGuard _(m_lock); ASSERT(!m_disk_cache.has_value()); - m_disk_cache = DiskCache(sector_size(), *this); + m_disk_cache.emplace(sector_size(), *this); } BAN::ErrorOr StorageDevice::sync_disk_cache()