Limit extfs device cache to 10% of system memory.

This commit is contained in:
Jonas 'Sortie' Termansen 2015-09-27 16:50:12 +02:00
parent 4839a97d91
commit ec990882b0
4 changed files with 63 additions and 16 deletions

View File

@ -31,7 +31,17 @@
#include "device.h" #include "device.h"
#include "ioleast.h" #include "ioleast.h"
Block::Block()
{
this->block_data = NULL;
}
Block::Block(Device* device, uint32_t block_id) 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->modify_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
this->transit_done_cond = PTHREAD_COND_INITIALIZER; 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->block_id = block_id;
this->dirty = false; this->dirty = false;
this->is_in_transit = false; this->is_in_transit = false;
this->block_data = NULL;
} }
Block::~Block() Block::~Block()
{
Destruct();
delete[] block_data;
}
void Block::Destruct()
{ {
Sync(); Sync();
Unlink(); Unlink();
delete[] block_data;
} }
void Block::Refer() void Block::Refer()
@ -64,11 +78,12 @@ void Block::Refer()
void Block::Unref() void Block::Unref()
{ {
if ( !--reference_count ) if ( !--reference_count )
{
#if 0 #if 0
device->block_count--;
delete this; delete this;
#else
{};
#endif #endif
}
} }
void Block::Sync() void Block::Sync()

View File

@ -28,8 +28,11 @@ class Device;
class Block class Block
{ {
public: public:
Block();
Block(Device* device, uint32_t block_id); Block(Device* device, uint32_t block_id);
~Block(); ~Block();
void Construct(Device* device, uint32_t block_id);
void Destruct();
public: public:
pthread_mutex_t modify_lock; pthread_mutex_t modify_lock;

View File

@ -61,6 +61,15 @@ Device::Device(int fd, const char* path, uint32_t block_size, bool write)
this->has_sync_thread = false; this->has_sync_thread = false;
this->sync_thread_should_exit = false; this->sync_thread_should_exit = false;
this->sync_in_transit = 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() Device::~Device()
@ -88,17 +97,37 @@ void Device::SpawnSyncThread()
pthread_create(&this->sync_thread, NULL, Device__SyncThread, this) == 0; 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) Block* Device::GetBlock(uint32_t block_id)
{ {
if ( Block* block = GetCachedBlock(block_id) ) if ( Block* block = GetCachedBlock(block_id) )
return block; return block;
uint8_t* data = new uint8_t[block_size]; Block* block = AllocateBlock();
if ( !data ) // TODO: Use operator new nothrow! if ( !block )
return NULL; return NULL;
Block* block = new Block(this, block_id); block->Construct(this, block_id);
if ( !block ) // TODO: Use operator new nothrow!
return delete[] data, (Block*) NULL;
block->block_data = data;
off_t file_offset = (off_t) block_size * (off_t) block_id; off_t file_offset = (off_t) block_size * (off_t) block_id;
preadall(fd, block->block_data, block_size, file_offset); preadall(fd, block->block_data, block_size, file_offset);
block->Prelink(); block->Prelink();
@ -115,13 +144,10 @@ Block* Device::GetBlockZeroed(uint32_t block_id)
block->FinishWrite(); block->FinishWrite();
return block; return block;
} }
uint8_t* data = new uint8_t[block_size]; Block* block = AllocateBlock();
if ( !data ) // TODO: Use operator new nothrow! if ( !block )
return NULL; return NULL;
Block* block = new Block(this, block_id); block->Construct(this, block_id);
if ( !block ) // TODO: Use operator new nothrow!
return delete[] data, (Block*) NULL;
block->block_data = data;
memset(block->block_data, 0, block_size); memset(block->block_data, 0, block_size);
block->Prelink(); block->Prelink();
block->BeginWrite(); block->BeginWrite();

View File

@ -50,9 +50,12 @@ public:
bool has_sync_thread; bool has_sync_thread;
bool sync_thread_should_exit; bool sync_thread_should_exit;
bool sync_in_transit; bool sync_in_transit;
size_t block_count;
size_t block_limit;
public: public:
void SpawnSyncThread(); void SpawnSyncThread();
Block* AllocateBlock();
Block* GetBlock(uint32_t block_id); Block* GetBlock(uint32_t block_id);
Block* GetBlockZeroed(uint32_t block_id); Block* GetBlockZeroed(uint32_t block_id);
Block* GetCachedBlock(uint32_t block_id); Block* GetCachedBlock(uint32_t block_id);