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
09c1aa44d8
commit
b924c85669
|
@ -36,6 +36,7 @@ namespace Kernel
|
||||||
const size_t m_sector_size;
|
const size_t m_sector_size;
|
||||||
StorageDevice& m_device;
|
StorageDevice& m_device;
|
||||||
BAN::Vector<PageCache> m_cache;
|
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::ErrorOr<void> DiskCache::sync()
|
||||||
{
|
{
|
||||||
BAN::Vector<uint8_t> sector_buffer;
|
ASSERT(&PageTable::current() == &PageTable::kernel());
|
||||||
TRY(sector_buffer.resize(m_sector_size));
|
auto& page_table = PageTable::kernel();
|
||||||
|
|
||||||
PageTable& page_table = PageTable::current();
|
|
||||||
LockGuard page_table_locker(page_table);
|
|
||||||
ASSERT(page_table.is_page_free(0));
|
|
||||||
|
|
||||||
for (auto& cache : m_cache)
|
for (auto& cache : m_cache)
|
||||||
{
|
{
|
||||||
for (int i = 0; cache.dirty_mask; i++)
|
if (cache.dirty_mask == 0)
|
||||||
{
|
|
||||||
if (!(cache.dirty_mask & (1 << i)))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
{
|
{
|
||||||
CriticalScope _;
|
LockGuard _(page_table);
|
||||||
|
ASSERT(page_table.is_page_free(0));
|
||||||
|
|
||||||
page_table.map_page_at(cache.paddr, 0, PageTable::Flags::Present);
|
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);
|
page_table.unmap_page(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(m_device.write_sectors_impl(cache.first_sector + i, 1, sector_buffer.data()));
|
uint8_t sector_start = 0;
|
||||||
cache.dirty_mask &= ~(1 << i);
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -260,7 +260,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
ASSERT(!m_disk_cache.has_value());
|
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()
|
BAN::ErrorOr<void> StorageDevice::sync_disk_cache()
|
||||||
|
|
Loading…
Reference in New Issue