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.
This commit is contained in:
Bananymous 2023-09-27 00:32:13 +03:00
parent c33e658f98
commit 11db49e2d3
3 changed files with 38 additions and 19 deletions
kernel
include/kernel/Storage
kernel/Storage

View File

@ -36,6 +36,7 @@ namespace Kernel
const size_t m_sector_size;
StorageDevice& m_device;
BAN::Vector<PageCache> m_cache;
BAN::Array<uint8_t, PAGE_SIZE> m_sync_cache;
};
}

View File

@ -118,32 +118,50 @@ namespace Kernel
BAN::ErrorOr<void> DiskCache::sync()
{
BAN::Vector<uint8_t> 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 & (1 << i)))
if (cache.dirty_mask == 0)
continue;
{
CriticalScope _;
LockGuard _(page_table);
ASSERT(page_table.is_page_free(0));
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
memcpy(sector_buffer.data(), (void*)(i * m_sector_size), m_sector_size);
memcpy(m_sync_cache.data(), (void*)0, PAGE_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);
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 {};
}

View File

@ -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<void> StorageDevice::sync_disk_cache()