#include "fs/devices/BlockDevice.h" #include "arch/MMU.h" #include BlockDevice::BlockDevice(u64 block_size, u64 num_blocks) : m_cache(), m_block_size(block_size), m_num_blocks(num_blocks) { } Result BlockDevice::read(u8* buf, usize offset, usize length) const { if (length == 0) return 0; if (offset > size()) return 0; if (offset + length > size()) length = size() - offset; const usize saved = length; auto read_data = [&](u64 off, u64 len) -> Result { const u64 block = offset / m_block_size; m_cache.lock(); auto guard = make_scope_guard([&] { m_cache.unlock(); }); auto* entry = TRY(m_cache.fetch_entry(block)); if (entry->buffer.is_empty()) { // TODO: What if the cache needs clearing in the middle of try_resize()? That could lead to some weird // state... TRY(entry->buffer.try_resize(m_block_size)); TRY(read_block(entry->buffer, block)); } memcpy(buf, entry->buffer.data() + off, len); offset += len; length -= len; buf += len; return {}; }; if (offset % m_block_size) { const u64 off = offset % m_block_size; const u64 len = min(m_block_size - off, length); TRY(read_data(off, len)); } while (length >= m_block_size) { TRY(read_data(0, m_block_size)); } if (length) { TRY(read_data(0, length)); } return saved; }