diff options
Diffstat (limited to 'Source/Kernel/VFS')
-rw-r--r-- | Source/Kernel/VFS/BlockCache.class.cpp | 89 | ||||
-rw-r--r-- | Source/Kernel/VFS/BlockCache.class.h | 32 | ||||
-rw-r--r-- | Source/Kernel/VFS/Part.ns.cpp | 2 | ||||
-rw-r--r-- | Source/Kernel/VFS/Partition.class.cpp | 8 | ||||
-rw-r--r-- | Source/Kernel/VFS/Partition.class.h | 2 | ||||
-rw-r--r-- | Source/Kernel/VFS/VFS.ns.cpp | 1 |
6 files changed, 129 insertions, 5 deletions
diff --git a/Source/Kernel/VFS/BlockCache.class.cpp b/Source/Kernel/VFS/BlockCache.class.cpp new file mode 100644 index 0000000..458faf6 --- /dev/null +++ b/Source/Kernel/VFS/BlockCache.class.cpp @@ -0,0 +1,89 @@ +#include <DeviceManager/Time.ns.h> + +template <typename T> +BlockCache<T>::BlockCache(T* dev) { + m_dev = dev; + m_count = 0; +} + +template <typename T> +BlockCache<T>::~BlockCache() { + sync(); + m_count = 0; + delete m_cache; + delete m_cacheInfo; +} + +template <typename T> +void BlockCache<T>::sync() { + for (u32int i = 0; i < m_count; i++) { + if (m_cacheInfo[i].dirty) m_dev->writeBlocks(m_cacheInfo[i].id, 1, m_cache + (i * m_dev->getBlockSize())); + } +} + +template <typename T> +void BlockCache<T>::init(u32int count) { + m_count = count; + m_cacheInfo = new cached_block_t[count]; + for (u32int i = 0; i < m_count; i++) { + m_cacheInfo[i].id = 0; + m_cacheInfo[i].lastuse = 0; + m_cacheInfo[i].dirty = false; + } + m_cache = (u8int*)Mem::alloc(m_count * m_dev->getBlockSize()); +} + +template <typename T> +bool BlockCache<T>::setCache(u64int block, u8int* data, bool dirty) { + u32int best = 0; + for (u32int i = 0; i < m_count; i++) { + if (m_cacheInfo[i].id == block) { + best = i; + break; + } + if (m_cacheInfo[i].lastuse < m_cacheInfo[best].lastuse) best = i; + } + if (best >= m_count) return false; + if (m_cacheInfo[best].dirty && (m_cacheInfo[best].id != block or !dirty)) + m_dev->writeBlocks(m_cacheInfo[best].id, 1, m_cache + (best * m_dev->getBlockSize())); + m_cacheInfo[best].id = block; + m_cacheInfo[best].lastuse = Time::uptime(); + m_cacheInfo[best].dirty = dirty; + memcpy(m_cache + (best * m_dev->getBlockSize()), data, m_dev->getBlockSize()); + return true; +} + +template <typename T> +bool BlockCache<T>::getCache(u64int block, u8int* data) { + for (u32int i = 0; i < m_count; i++) { + if (m_cacheInfo[i].id == block && m_cacheInfo[i].lastuse != 0) { + m_cacheInfo[i].lastuse = Time::uptime(); + memcpy(data, m_cache + (i * m_dev->getBlockSize()), m_dev->getBlockSize()); + return true; + } + } + return false; +} + +template <typename T> +bool BlockCache<T>::readBlocks(u64int startblock, u32int count, u8int* data) { + if (count == 1) { + if (getCache(startblock, data)) return true; + if (!m_dev->readBlocks(startblock, count, data)) return false; + setCache(startblock, data); + return true; + } else { + return m_dev->readBlocks(startblock, count, data); + } +} + +template <typename T> +bool BlockCache<T>::writeBlocks(u64int startblock, u32int count, u8int* data) { + if (m_dev->readOnly()) return false; + if (count == 1) { + if (!setCache(startblock, data, true)) return m_dev->writeBlocks(startblock, count, data); + return true; + } else { + return m_dev->writeBlocks(startblock, count, data); + } +} diff --git a/Source/Kernel/VFS/BlockCache.class.h b/Source/Kernel/VFS/BlockCache.class.h new file mode 100644 index 0000000..0b26180 --- /dev/null +++ b/Source/Kernel/VFS/BlockCache.class.h @@ -0,0 +1,32 @@ +#ifndef DEF_BLOCKCACHE_CLASS_H +#define DEF_BLOCKCACHE_CLASS_H + +template <typename T> +class BlockCache { + private: + T* m_dev; + u32int m_count; + struct cached_block_t { + u64int id; + u32int lastuse; + bool dirty; + } *m_cacheInfo; + u8int* m_cache; + + void sync(); + bool setCache(u64int block, u8int* data, bool dirty = false); + bool getCache(u64int block, u8int* data); + + public: + BlockCache(T* dev); + ~BlockCache(); + void init(u32int count); + + bool readBlocks(u64int startblock, u32int count, u8int* data); + bool writeBlocks(u64int startblock, u32int count, u8int* data); + +}; + +#include "BlockCache.class.cpp" + +#endif diff --git a/Source/Kernel/VFS/Part.ns.cpp b/Source/Kernel/VFS/Part.ns.cpp index 1bd6a8e..9ead6b5 100644 --- a/Source/Kernel/VFS/Part.ns.cpp +++ b/Source/Kernel/VFS/Part.ns.cpp @@ -57,7 +57,7 @@ u32int getDeviceID(BlockDevice* dev) { } BlockDevice* dev(String _class, u32int idx) { - if (_class.empty()) _class = "block"; + if (_class.empty()) return devices[idx]; for (u32int i = 0; i < devices.size(); i++) { String devclass = devices[i]->getClass(); if (devclass == _class or (devclass.size() > _class.size() and devclass.substr(0, _class.size()) == _class)) { diff --git a/Source/Kernel/VFS/Partition.class.cpp b/Source/Kernel/VFS/Partition.class.cpp index b62f33c..1476b14 100644 --- a/Source/Kernel/VFS/Partition.class.cpp +++ b/Source/Kernel/VFS/Partition.class.cpp @@ -2,21 +2,23 @@ using namespace CMem; //For memcpy -Partition::Partition(BlockDevice* dev, u8int partnumber, u64int startblock, u64int blockcount) { +Partition::Partition(BlockDevice* dev, u8int partnumber, u64int startblock, u64int blockcount) +: m_cache(dev) { m_device = dev; m_partnumber = partnumber; m_startblock = startblock; m_blockcount = blockcount; + m_cache.init(10 + (m_device->blocks() / 1000 > 100 ? 100 : m_device->blocks() / 1000)); } bool Partition::readBlocks(u64int startblock, u32int count, u8int *data) { if (startblock + count > m_startblock + m_blockcount) return false; - return m_device->readBlocks(startblock - m_startblock, count, data); + return m_cache.readBlocks(startblock - m_startblock, count, data); } bool Partition::writeBlocks(u64int startblock, u32int count, u8int *data) { if (startblock + count > m_startblock + m_blockcount) return false; - return m_device->writeBlocks(startblock - m_startblock, count, data); + return m_cache.writeBlocks(startblock - m_startblock, count, data); } bool Partition::read(u64int start, u32int length, u8int *data) { diff --git a/Source/Kernel/VFS/Partition.class.h b/Source/Kernel/VFS/Partition.class.h index 8df1c4f..f511074 100644 --- a/Source/Kernel/VFS/Partition.class.h +++ b/Source/Kernel/VFS/Partition.class.h @@ -2,10 +2,12 @@ #define DEF_PARTITION_CLASS_H #include <Devices/BlockDevice.proto.h> +#include <VFS/BlockCache.class.h> class Partition { private: BlockDevice* m_device; + BlockCache<BlockDevice> m_cache; u64int m_startblock, m_blockcount; u8int m_partnumber; //Partition number in partition table of device diff --git a/Source/Kernel/VFS/VFS.ns.cpp b/Source/Kernel/VFS/VFS.ns.cpp index 6a5fe4e..3b59c5a 100644 --- a/Source/Kernel/VFS/VFS.ns.cpp +++ b/Source/Kernel/VFS/VFS.ns.cpp @@ -90,7 +90,6 @@ bool mount(String str, VirtualTerminal* vt, multiboot_info_t *mbd) { *vt << "Syntax: <mountpoint>:[<dev_class>]:<dev_id>:<part_id>[:<fs_type>[:[ro|rw]]]\n"; return false; } - if (fs[1] == "") fs[1] = "block"; if (fs.size() < 5) fs.push(""); if (fs.size() < 6) fs.push("ro"); //By default, mount file systems read-only BlockDevice* d = Part::dev(fs[1], fs[2].toInt()); |