Limit extfs device cache to 10% of system memory.
This commit is contained in:
parent
4839a97d91
commit
ec990882b0
4 changed files with 63 additions and 16 deletions
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue