From ec990882b0da2030af2eaf59accd2b613e6d022a Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sun, 27 Sep 2015 16:50:12 +0200 Subject: [PATCH] Limit extfs device cache to 10% of system memory. --- ext/block.cpp | 23 +++++++++++++++++++---- ext/block.h | 3 +++ ext/device.cpp | 50 ++++++++++++++++++++++++++++++++++++++------------ ext/device.h | 3 +++ 4 files changed, 63 insertions(+), 16 deletions(-) diff --git a/ext/block.cpp b/ext/block.cpp index b8400dfd..4b6b3f54 100644 --- a/ext/block.cpp +++ b/ext/block.cpp @@ -31,7 +31,17 @@ #include "device.h" #include "ioleast.h" +Block::Block() +{ + this->block_data = NULL; +} + Block::Block(Device* device, uint32_t block_id) +{ + Construct(device, block_id); +} + +void Block::Construct(Device* device, uint32_t block_id) { this->modify_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; this->transit_done_cond = PTHREAD_COND_INITIALIZER; @@ -46,14 +56,18 @@ Block::Block(Device* device, uint32_t block_id) this->block_id = block_id; this->dirty = false; this->is_in_transit = false; - this->block_data = NULL; } Block::~Block() +{ + Destruct(); + delete[] block_data; +} + +void Block::Destruct() { Sync(); Unlink(); - delete[] block_data; } void Block::Refer() @@ -64,11 +78,12 @@ void Block::Refer() void Block::Unref() { if ( !--reference_count ) + { #if 0 + device->block_count--; delete this; -#else - {}; #endif + } } void Block::Sync() diff --git a/ext/block.h b/ext/block.h index 2b1be84e..84381c27 100644 --- a/ext/block.h +++ b/ext/block.h @@ -28,8 +28,11 @@ class Device; class Block { public: + Block(); Block(Device* device, uint32_t block_id); ~Block(); + void Construct(Device* device, uint32_t block_id); + void Destruct(); public: pthread_mutex_t modify_lock; diff --git a/ext/device.cpp b/ext/device.cpp index e85b81c4..b0c6ac14 100644 --- a/ext/device.cpp +++ b/ext/device.cpp @@ -61,6 +61,15 @@ Device::Device(int fd, const char* path, uint32_t block_size, bool write) this->has_sync_thread = false; this->sync_thread_should_exit = false; this->sync_in_transit = false; + this->block_count = 0; +#ifdef __sortix__ + // TODO: This isn't scaleable if there's multiple filesystems mounted. + size_t memory; + memstat(NULL, &memory); + this->block_limit = (memory / 10) / block_size; +#else + this->block_limit = 32768; +#endif } Device::~Device() @@ -88,17 +97,37 @@ void Device::SpawnSyncThread() pthread_create(&this->sync_thread, NULL, Device__SyncThread, this) == 0; } +Block* Device::AllocateBlock() +{ + if ( block_limit <= block_count ) + { + for ( Block* block = lru_block; block; block = block->prev_block ) + { + if ( block->reference_count ) + continue; + block->Destruct(); // Syncs. + return block; + } + } + uint8_t* data = new uint8_t[block_size]; + if ( !data ) // TODO: Use operator new nothrow! + return NULL; + Block* block = new Block(); + if ( !block ) // TODO: Use operator new nothrow! + return delete[] data, (Block*) NULL; + block->block_data = data; + block_count++; + return block; +} + Block* Device::GetBlock(uint32_t block_id) { if ( Block* block = GetCachedBlock(block_id) ) return block; - uint8_t* data = new uint8_t[block_size]; - if ( !data ) // TODO: Use operator new nothrow! + Block* block = AllocateBlock(); + if ( !block ) return NULL; - Block* block = new Block(this, block_id); - if ( !block ) // TODO: Use operator new nothrow! - return delete[] data, (Block*) NULL; - block->block_data = data; + block->Construct(this, block_id); off_t file_offset = (off_t) block_size * (off_t) block_id; preadall(fd, block->block_data, block_size, file_offset); block->Prelink(); @@ -115,13 +144,10 @@ Block* Device::GetBlockZeroed(uint32_t block_id) block->FinishWrite(); return block; } - uint8_t* data = new uint8_t[block_size]; - if ( !data ) // TODO: Use operator new nothrow! + Block* block = AllocateBlock(); + if ( !block ) return NULL; - Block* block = new Block(this, block_id); - if ( !block ) // TODO: Use operator new nothrow! - return delete[] data, (Block*) NULL; - block->block_data = data; + block->Construct(this, block_id); memset(block->block_data, 0, block_size); block->Prelink(); block->BeginWrite(); diff --git a/ext/device.h b/ext/device.h index 586f3307..c52fa04e 100644 --- a/ext/device.h +++ b/ext/device.h @@ -50,9 +50,12 @@ public: bool has_sync_thread; bool sync_thread_should_exit; bool sync_in_transit; + size_t block_count; + size_t block_limit; public: void SpawnSyncThread(); + Block* AllocateBlock(); Block* GetBlock(uint32_t block_id); Block* GetBlockZeroed(uint32_t block_id); Block* GetCachedBlock(uint32_t block_id);