Compare commits
59 Commits
b95d495815
...
5099b2b0f4
Author | SHA1 | Date | |
---|---|---|---|
5099b2b0f4 | |||
961a127ec4 | |||
bd4376d946 | |||
9154919be8 | |||
1a85c13036 | |||
55e3b6bbf9 | |||
c5b295c38c | |||
c483b3a3e6 | |||
c51ccf6948 | |||
574cf1f12b | |||
3d7f783894 | |||
52afb2dfe0 | |||
6a443ffbc2 | |||
6a6e508a7e | |||
f9c8bb3346 | |||
b69897e3c2 | |||
d59cf7733b | |||
211b45cec4 | |||
9ac6112068 | |||
8ebcb9c386 | |||
6716bf687d | |||
e4e1f8a98f | |||
7739b37b4b | |||
deb5137322 | |||
282ce0aabb | |||
81464f94ce | |||
fb4c874196 | |||
4478eae9e8 | |||
8f45a683d0 | |||
42269adb44 | |||
82dc1e21e6 | |||
21516eef59 | |||
707c0950a0 | |||
1e22ab2760 | |||
525c7c66f4 | |||
eb193b6559 | |||
92c96a0bd8 | |||
3081c78edd | |||
a8777e373e | |||
f1f5909e84 | |||
afc2a19c8d | |||
b253c3c8d8 | |||
338446e2d8 | |||
591c3d5c59 | |||
e2e136f292 | |||
e4aa774082 | |||
8b1071a5cd | |||
5db74945e2 | |||
452c17677f | |||
55bd8896d2 | |||
19773c952f | |||
6485c78428 | |||
21271bfcc3 | |||
db27035e24 | |||
e5162fac7d | |||
6824b719e0 | |||
cd2b8a1ab5 | |||
65a900ea53 | |||
d6c4ee5e7b |
@ -52,14 +52,12 @@ set(SOURCES
|
|||||||
src/fs/Mount.cpp
|
src/fs/Mount.cpp
|
||||||
src/fs/MBR.cpp
|
src/fs/MBR.cpp
|
||||||
src/fs/GPT.cpp
|
src/fs/GPT.cpp
|
||||||
src/fs/StorageCache.cpp
|
|
||||||
src/net/UnixSocket.cpp
|
src/net/UnixSocket.cpp
|
||||||
src/fs/tmpfs/FileSystem.cpp
|
src/fs/tmpfs/FileSystem.cpp
|
||||||
src/fs/tmpfs/Inode.cpp
|
src/fs/tmpfs/Inode.cpp
|
||||||
src/fs/ext2/FileSystem.cpp
|
src/fs/ext2/FileSystem.cpp
|
||||||
src/fs/ext2/Inode.cpp
|
src/fs/ext2/Inode.cpp
|
||||||
src/fs/devices/DeviceRegistry.cpp
|
src/fs/devices/DeviceRegistry.cpp
|
||||||
src/fs/devices/BlockDevice.cpp
|
|
||||||
src/fs/devices/NullDevice.cpp
|
src/fs/devices/NullDevice.cpp
|
||||||
src/fs/devices/ZeroDevice.cpp
|
src/fs/devices/ZeroDevice.cpp
|
||||||
src/fs/devices/FullDevice.cpp
|
src/fs/devices/FullDevice.cpp
|
||||||
|
@ -11,5 +11,4 @@ target_compile_definitions(moon PRIVATE EXT2_DEBUG)
|
|||||||
target_compile_definitions(moon PRIVATE DEVICE_REGISTRY_DEBUG)
|
target_compile_definitions(moon PRIVATE DEVICE_REGISTRY_DEBUG)
|
||||||
target_compile_definitions(moon PRIVATE FORK_DEBUG)
|
target_compile_definitions(moon PRIVATE FORK_DEBUG)
|
||||||
target_compile_definitions(moon PRIVATE MOUNT_DEBUG)
|
target_compile_definitions(moon PRIVATE MOUNT_DEBUG)
|
||||||
target_compile_definitions(moon PRIVATE CACHE_DEBUG)
|
|
||||||
target_compile_options(moon PRIVATE -fsanitize=undefined)
|
target_compile_options(moon PRIVATE -fsanitize=undefined)
|
||||||
|
@ -739,26 +739,66 @@ Result<String> ATA::Drive::create_drive_name(ATA::Drive* drive)
|
|||||||
|
|
||||||
Result<SharedPtr<Device>> ATADevice::create(ATA::Drive* drive)
|
Result<SharedPtr<Device>> ATADevice::create(ATA::Drive* drive)
|
||||||
{
|
{
|
||||||
auto device = TRY(adopt_shared_if_nonnull(new (std::nothrow) ATADevice(drive)));
|
auto device = TRY(adopt_shared_if_nonnull(new (std::nothrow) ATADevice()));
|
||||||
|
device->m_drive = drive;
|
||||||
device->m_device_path = TRY(ATA::Drive::create_drive_name(drive));
|
device->m_device_path = TRY(ATA::Drive::create_drive_name(drive));
|
||||||
TRY(DeviceRegistry::register_special_device(DeviceRegistry::Disk, next_minor++, device, 0400));
|
TRY(DeviceRegistry::register_special_device(DeviceRegistry::Disk, next_minor++, device, 0400));
|
||||||
return (SharedPtr<Device>)device;
|
return (SharedPtr<Device>)device;
|
||||||
}
|
}
|
||||||
|
|
||||||
ATADevice::ATADevice(ATA::Drive* drive) : BlockDevice(drive->block_size(), drive->block_count()), m_drive(drive)
|
Result<u64> ATADevice::read(u8* buf, usize offset, usize size) const
|
||||||
{
|
{
|
||||||
}
|
if (size == 0) return 0;
|
||||||
|
|
||||||
|
if (offset > m_drive->capacity()) return 0;
|
||||||
|
if (offset + size > m_drive->capacity()) size = m_drive->capacity() - offset;
|
||||||
|
|
||||||
|
usize length = size;
|
||||||
|
|
||||||
|
auto block_size = m_drive->block_size();
|
||||||
|
|
||||||
Result<void> ATADevice::read_block(Buffer& buf, u64 block) const
|
|
||||||
{
|
|
||||||
ScopedKMutexLock<100> lock(m_drive->channel()->lock());
|
ScopedKMutexLock<100> lock(m_drive->channel()->lock());
|
||||||
|
|
||||||
if (buf.size() != m_drive->block_size())
|
Buffer temp;
|
||||||
|
|
||||||
|
if (offset % block_size)
|
||||||
{
|
{
|
||||||
kwarnln("ata: error while reading block %lu: cache entry size mismatch (%lu), data=%p", block, buf.size(),
|
// The size we need to read to round up to a block.
|
||||||
buf.data());
|
usize extra_size = block_size - (offset % block_size);
|
||||||
fail("Cache entry size mismatch");
|
// Maybe we don't even want enough to get to the next block?
|
||||||
|
if (extra_size > size) extra_size = size;
|
||||||
|
|
||||||
|
TRY(temp.try_resize(block_size));
|
||||||
|
|
||||||
|
TRY(m_drive->read_lba(offset / block_size, temp.data(), 1));
|
||||||
|
memcpy(buf, temp.data() + (offset % block_size), extra_size);
|
||||||
|
offset += extra_size;
|
||||||
|
size -= extra_size;
|
||||||
|
buf += extra_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_drive->read_lba(block, buf.data(), 1);
|
while (size >= ARCH_PAGE_SIZE)
|
||||||
|
{
|
||||||
|
TRY(m_drive->read_lba(offset / block_size, buf, ARCH_PAGE_SIZE / block_size));
|
||||||
|
offset += ARCH_PAGE_SIZE;
|
||||||
|
size -= ARCH_PAGE_SIZE;
|
||||||
|
buf += ARCH_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (size >= block_size)
|
||||||
|
{
|
||||||
|
TRY(m_drive->read_lba(offset / block_size, buf, 1));
|
||||||
|
offset += block_size;
|
||||||
|
size -= block_size;
|
||||||
|
buf += block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
TRY(temp.try_resize(block_size));
|
||||||
|
TRY(m_drive->read_lba(offset / block_size, temp.data(), 1));
|
||||||
|
memcpy(buf, temp.data(), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "arch/PCI.h"
|
#include "arch/PCI.h"
|
||||||
#include "fs/devices/BlockDevice.h"
|
|
||||||
#include "fs/devices/DeviceRegistry.h"
|
#include "fs/devices/DeviceRegistry.h"
|
||||||
#include "lib/KMutex.h"
|
#include "lib/KMutex.h"
|
||||||
#include <luna/Atomic.h>
|
#include <luna/Atomic.h>
|
||||||
@ -257,6 +256,7 @@ namespace ATA
|
|||||||
Controller* m_controller;
|
Controller* m_controller;
|
||||||
u8 m_channel_index;
|
u8 m_channel_index;
|
||||||
bool m_is_pci_native_mode;
|
bool m_is_pci_native_mode;
|
||||||
|
|
||||||
u8 m_interrupt_line;
|
u8 m_interrupt_line;
|
||||||
|
|
||||||
KMutex<100> m_lock {};
|
KMutex<100> m_lock {};
|
||||||
@ -297,25 +297,44 @@ namespace ATA
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ATADevice : public BlockDevice
|
class ATADevice : public Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Initializer for DeviceRegistry.
|
// Initializer for DeviceRegistry.
|
||||||
static Result<SharedPtr<Device>> create(ATA::Drive* drive);
|
static Result<SharedPtr<Device>> create(ATA::Drive* drive);
|
||||||
|
|
||||||
Result<void> read_block(Buffer& buf, u64 block) const override;
|
Result<usize> read(u8*, usize, usize) const override;
|
||||||
|
|
||||||
|
Result<usize> write(const u8*, usize, usize) override
|
||||||
|
{
|
||||||
|
return err(ENOTSUP);
|
||||||
|
}
|
||||||
|
|
||||||
bool will_block_if_read() const override
|
bool will_block_if_read() const override
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_block_device() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize size() const override
|
||||||
|
{
|
||||||
|
return m_drive->capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<usize> block_size() const override
|
||||||
|
{
|
||||||
|
return m_drive->block_size();
|
||||||
|
}
|
||||||
|
|
||||||
StringView device_path() const override
|
StringView device_path() const override
|
||||||
{
|
{
|
||||||
return m_device_path.view();
|
return m_device_path.view();
|
||||||
}
|
}
|
||||||
|
|
||||||
ATADevice(ATA::Drive* drive);
|
|
||||||
virtual ~ATADevice() = default;
|
virtual ~ATADevice() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
#include "fs/StorageCache.h"
|
|
||||||
#include "Log.h"
|
|
||||||
#include <luna/ScopeGuard.h>
|
|
||||||
|
|
||||||
static LinkedList<StorageCache> g_storage_caches;
|
|
||||||
|
|
||||||
Result<StorageCache::CacheEntry*> StorageCache::fetch_entry(u64 block)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
CacheEntry* entry = m_cache_entries.try_get_ref(block);
|
|
||||||
if (entry && !entry->buffer.is_empty()) return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
CacheEntry entry {};
|
|
||||||
TRY(m_cache_entries.try_set(block, move(entry)));
|
|
||||||
|
|
||||||
#ifdef CACHE_DEBUG
|
|
||||||
kdbgln("cache: Created new cache entry for block %lu", block);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return m_cache_entries.try_get_ref(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StorageCache::clear()
|
|
||||||
{
|
|
||||||
ScopedKMutexLock<100> lock(m_mutex);
|
|
||||||
|
|
||||||
m_cache_entries.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageCache::StorageCache()
|
|
||||||
{
|
|
||||||
g_storage_caches.append(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageCache::~StorageCache()
|
|
||||||
{
|
|
||||||
g_storage_caches.remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void StorageCache::clear_caches()
|
|
||||||
{
|
|
||||||
for (auto* cache : g_storage_caches) { cache->clear(); }
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "lib/KMutex.h"
|
|
||||||
#include <luna/Buffer.h>
|
|
||||||
#include <luna/HashMap.h>
|
|
||||||
#include <luna/LinkedList.h>
|
|
||||||
|
|
||||||
class StorageCache : public LinkedListNode<StorageCache>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct CacheEntry
|
|
||||||
{
|
|
||||||
Buffer buffer {};
|
|
||||||
};
|
|
||||||
|
|
||||||
void lock()
|
|
||||||
{
|
|
||||||
return m_mutex.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlock()
|
|
||||||
{
|
|
||||||
return m_mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<CacheEntry*> fetch_entry(u64 block);
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
static void clear_caches();
|
|
||||||
|
|
||||||
StorageCache();
|
|
||||||
~StorageCache();
|
|
||||||
|
|
||||||
private:
|
|
||||||
HashMap<u64, CacheEntry> m_cache_entries;
|
|
||||||
KMutex<100> m_mutex;
|
|
||||||
};
|
|
@ -1,51 +0,0 @@
|
|||||||
#include "fs/devices/BlockDevice.h"
|
|
||||||
#include "arch/MMU.h"
|
|
||||||
#include <luna/Common.h>
|
|
||||||
|
|
||||||
BlockDevice::BlockDevice(u64 block_size, u64 num_blocks) : m_cache(), m_block_size(block_size), m_num_blocks(num_blocks)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<usize> 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<void> {
|
|
||||||
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;
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "fs/StorageCache.h"
|
|
||||||
#include "fs/devices/Device.h"
|
|
||||||
|
|
||||||
class BlockDevice : public Device
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BlockDevice(u64 block_size, u64 num_blocks);
|
|
||||||
|
|
||||||
Result<usize> read(u8* buf, usize offset, usize length) const override;
|
|
||||||
|
|
||||||
virtual Result<void> read_block(Buffer& buf, u64 block) const = 0;
|
|
||||||
|
|
||||||
Result<usize> write(const u8*, usize, usize) override
|
|
||||||
{
|
|
||||||
return err(ENOTSUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
usize size() const override
|
|
||||||
{
|
|
||||||
return m_block_size * m_num_blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_block_device() const override
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<usize> block_size() const override
|
|
||||||
{
|
|
||||||
return m_block_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~BlockDevice() = default;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
mutable StorageCache m_cache;
|
|
||||||
u64 m_block_size;
|
|
||||||
u64 m_num_blocks;
|
|
||||||
};
|
|
@ -2,8 +2,6 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include <luna/Result.h>
|
#include <luna/Result.h>
|
||||||
#include <luna/SharedPtr.h>
|
#include <luna/SharedPtr.h>
|
||||||
#include <luna/StringView.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
class Device : public Shareable
|
class Device : public Shareable
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "arch/MMU.h"
|
#include "arch/MMU.h"
|
||||||
#include "fs/StorageCache.h"
|
|
||||||
#include "memory/KernelVM.h"
|
#include "memory/KernelVM.h"
|
||||||
#include "memory/MemoryMap.h"
|
#include "memory/MemoryMap.h"
|
||||||
#include <luna/Alignment.h>
|
#include <luna/Alignment.h>
|
||||||
@ -144,12 +143,7 @@ namespace MemoryManager
|
|||||||
|
|
||||||
usize index;
|
usize index;
|
||||||
bool ok = frame_bitmap->find_and_toggle(false, start_index).try_set_value(index);
|
bool ok = frame_bitmap->find_and_toggle(false, start_index).try_set_value(index);
|
||||||
if (!ok)
|
if (!ok) return err(ENOMEM);
|
||||||
{
|
|
||||||
kwarnln("OOM alert! Trying to free caches...");
|
|
||||||
StorageCache::clear_caches();
|
|
||||||
if (!frame_bitmap->find_and_toggle(false, start_index).try_set_value(index)) return err(ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
start_index = index + 1;
|
start_index = index + 1;
|
||||||
|
|
||||||
|
@ -49,11 +49,6 @@ template <typename K, typename V> struct HashMap
|
|||||||
return m_table.try_remove(HashPair<K, V> { key, {} });
|
return m_table.try_remove(HashPair<K, V> { key, {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
m_table.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HashTable<HashPair<K, V>> m_table;
|
HashTable<HashPair<K, V>> m_table;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user