forked from Bananymous/banan-os
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:
parent
c33e658f98
commit
11db49e2d3
kernel
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue