Refactor extfs dirty pattern to BeginWrite then FinishWrite pattern.

This commit is contained in:
Jonas 'Sortie' Termansen 2015-01-30 15:38:10 +01:00
parent 34a832dbf3
commit de21e9c8e2
11 changed files with 142 additions and 74 deletions

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013. Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015.
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free
@ -82,7 +82,11 @@ void Block::Sync()
pwriteall(device->fd, block_data, device->block_size, file_offset); pwriteall(device->fd, block_data, device->block_size, file_offset);
} }
void Block::Dirty() void Block::BeginWrite()
{
}
void Block::FinishWrite()
{ {
if ( !dirty ) if ( !dirty )
{ {

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013. Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015.
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free
@ -48,7 +48,8 @@ public:
void Refer(); void Refer();
void Unref(); void Unref();
void Sync(); void Sync();
void Dirty(); void BeginWrite();
void FinishWrite();
void Use(); void Use();
void Unlink(); void Unlink();
void Prelink(); void Prelink();

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013. Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015.
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free
@ -96,22 +96,25 @@ uint32_t BlockGroup::AllocateBlock()
for ( ; block_bitmap_chunk_i < num_bits; block_bitmap_chunk_i++ ) for ( ; block_bitmap_chunk_i < num_bits; block_bitmap_chunk_i++ )
if ( !checkbit(chunk_bits, block_bitmap_chunk_i) ) if ( !checkbit(chunk_bits, block_bitmap_chunk_i) )
{ {
block_bitmap_chunk->BeginWrite();
setbit(chunk_bits, block_bitmap_chunk_i); setbit(chunk_bits, block_bitmap_chunk_i);
block_bitmap_chunk->Dirty(); block_bitmap_chunk->FinishWrite();
BeginWrite();
data->bg_free_blocks_count--; data->bg_free_blocks_count--;
Dirty(); FinishWrite();
filesystem->BeginWrite();
filesystem->sb->s_free_blocks_count--; filesystem->sb->s_free_blocks_count--;
filesystem->Dirty(); filesystem->FinishWrite();
uint32_t group_block_id = chunk_offset + block_bitmap_chunk_i++; uint32_t group_block_id = chunk_offset + block_bitmap_chunk_i++;
uint32_t block_id = first_block_id + group_block_id; uint32_t block_id = first_block_id + group_block_id;
return block_id; return block_id;
} }
block_bitmap_chunk->Sync();
block_bitmap_chunk->Unref(); block_bitmap_chunk->Unref();
block_bitmap_chunk = NULL; block_bitmap_chunk = NULL;
} }
BeginWrite();
data->bg_free_blocks_count = 0; data->bg_free_blocks_count = 0;
Dirty(); FinishWrite();
return errno = ENOSPC, 0; return errno = ENOSPC, 0;
} }
@ -138,22 +141,25 @@ uint32_t BlockGroup::AllocateInode()
for ( ; inode_bitmap_chunk_i < num_bits; inode_bitmap_chunk_i++ ) for ( ; inode_bitmap_chunk_i < num_bits; inode_bitmap_chunk_i++ )
if ( !checkbit(chunk_bits, inode_bitmap_chunk_i) ) if ( !checkbit(chunk_bits, inode_bitmap_chunk_i) )
{ {
inode_bitmap_chunk->BeginWrite();
setbit(chunk_bits, inode_bitmap_chunk_i); setbit(chunk_bits, inode_bitmap_chunk_i);
inode_bitmap_chunk->Dirty(); inode_bitmap_chunk->FinishWrite();
BeginWrite();
data->bg_free_inodes_count--; data->bg_free_inodes_count--;
Dirty(); FinishWrite();
filesystem->BeginWrite();
filesystem->sb->s_free_inodes_count--; filesystem->sb->s_free_inodes_count--;
filesystem->Dirty(); filesystem->FinishWrite();
uint32_t group_inode_id = chunk_offset + inode_bitmap_chunk_i++; uint32_t group_inode_id = chunk_offset + inode_bitmap_chunk_i++;
uint32_t inode_id = first_inode_id + group_inode_id; uint32_t inode_id = first_inode_id + group_inode_id;
return inode_id; return inode_id;
} }
inode_bitmap_chunk->Sync();
inode_bitmap_chunk->Unref(); inode_bitmap_chunk->Unref();
inode_bitmap_chunk = NULL; inode_bitmap_chunk = NULL;
} }
BeginWrite();
data->bg_free_inodes_count = 0; data->bg_free_inodes_count = 0;
Dirty(); FinishWrite();
return errno = ENOSPC, 0; return errno = ENOSPC, 0;
} }
@ -166,7 +172,6 @@ void BlockGroup::FreeBlock(uint32_t block_id)
if ( !block_bitmap_chunk || chunk_id != block_alloc_chunk ) if ( !block_bitmap_chunk || chunk_id != block_alloc_chunk )
{ {
if ( block_bitmap_chunk ) if ( block_bitmap_chunk )
block_bitmap_chunk->Sync(),
block_bitmap_chunk->Unref(); block_bitmap_chunk->Unref();
block_alloc_chunk = chunk_id; block_alloc_chunk = chunk_id;
uint32_t block_id = data->bg_block_bitmap + block_alloc_chunk; uint32_t block_id = data->bg_block_bitmap + block_alloc_chunk;
@ -174,13 +179,16 @@ void BlockGroup::FreeBlock(uint32_t block_id)
block_bitmap_chunk_i = 0; block_bitmap_chunk_i = 0;
} }
block_bitmap_chunk->BeginWrite();
uint8_t* chunk_bits = block_bitmap_chunk->block_data; uint8_t* chunk_bits = block_bitmap_chunk->block_data;
clearbit(chunk_bits, chunk_bit); clearbit(chunk_bits, chunk_bit);
block_bitmap_chunk->Dirty(); block_bitmap_chunk->FinishWrite();
BeginWrite();
data->bg_free_blocks_count++; data->bg_free_blocks_count++;
Dirty(); FinishWrite();
filesystem->BeginWrite();
filesystem->sb->s_free_blocks_count++; filesystem->sb->s_free_blocks_count++;
filesystem->Dirty(); filesystem->FinishWrite();
} }
void BlockGroup::FreeInode(uint32_t inode_id) void BlockGroup::FreeInode(uint32_t inode_id)
@ -192,7 +200,6 @@ void BlockGroup::FreeInode(uint32_t inode_id)
if ( !inode_bitmap_chunk || chunk_id != inode_alloc_chunk ) if ( !inode_bitmap_chunk || chunk_id != inode_alloc_chunk )
{ {
if ( inode_bitmap_chunk ) if ( inode_bitmap_chunk )
inode_bitmap_chunk->Sync(),
inode_bitmap_chunk->Unref(); inode_bitmap_chunk->Unref();
inode_alloc_chunk = chunk_id; inode_alloc_chunk = chunk_id;
uint32_t block_id = data->bg_inode_bitmap + inode_alloc_chunk; uint32_t block_id = data->bg_inode_bitmap + inode_alloc_chunk;
@ -200,13 +207,16 @@ void BlockGroup::FreeInode(uint32_t inode_id)
inode_bitmap_chunk_i = 0; inode_bitmap_chunk_i = 0;
} }
inode_bitmap_chunk->BeginWrite();
uint8_t* chunk_bits = inode_bitmap_chunk->block_data; uint8_t* chunk_bits = inode_bitmap_chunk->block_data;
clearbit(chunk_bits, chunk_bit); clearbit(chunk_bits, chunk_bit);
inode_bitmap_chunk->Dirty(); inode_bitmap_chunk->FinishWrite();
BeginWrite();
data->bg_free_inodes_count++; data->bg_free_inodes_count++;
Dirty(); FinishWrite();
filesystem->BeginWrite();
filesystem->sb->s_free_inodes_count++; filesystem->sb->s_free_inodes_count++;
filesystem->Dirty(); filesystem->FinishWrite();
} }
void BlockGroup::Refer() void BlockGroup::Refer()
@ -223,15 +233,22 @@ void BlockGroup::Sync()
{ {
if ( block_bitmap_chunk ) if ( block_bitmap_chunk )
block_bitmap_chunk->Sync(); block_bitmap_chunk->Sync();
if ( inode_bitmap_chunk )
inode_bitmap_chunk->Sync();
if ( dirty ) if ( dirty )
data_block->Sync(); data_block->Sync();
dirty = false; dirty = false;
} }
void BlockGroup::Dirty() void BlockGroup::BeginWrite()
{
data_block->BeginWrite();
}
void BlockGroup::FinishWrite()
{ {
dirty = true; dirty = true;
data_block->Dirty(); data_block->FinishWrite();
Use(); Use();
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013. Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015.
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free
@ -60,7 +60,8 @@ public:
void Refer(); void Refer();
void Unref(); void Unref();
void Sync(); void Sync();
void Dirty(); void BeginWrite();
void FinishWrite();
void Use(); void Use();
void Unlink(); void Unlink();
void Prelink(); void Prelink();

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013. Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015.
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free
@ -70,15 +70,17 @@ Block* Device::GetBlockZeroed(uint32_t block_id)
{ {
if ( Block* block = GetCachedBlock(block_id) ) if ( Block* block = GetCachedBlock(block_id) )
{ {
block->BeginWrite();
memset(block->block_data, 0, block_size); memset(block->block_data, 0, block_size);
block->Dirty(); block->FinishWrite();
return block; return block;
} }
Block* block = new Block(this, block_id); Block* block = new Block(this, block_id);
block->block_data = new uint8_t[block_size]; block->block_data = new uint8_t[block_size];
memset(block->block_data, 0, block_size); memset(block->block_data, 0, block_size);
block->Prelink(); block->Prelink();
block->Dirty(); block->BeginWrite();
block->FinishWrite();
return block; return block;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013. Copyright(C) Jonas 'Sortie' Termansen 2013, 2014.
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free

View File

@ -305,9 +305,10 @@ void HandleUTimens(int chl, struct fsm_req_utimens* msg, Filesystem* fs)
if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; } if ( fs->num_inodes <= msg->ino ) { RespondError(chl, EBADF); return; }
Inode* inode = fs->GetInode((uint32_t) msg->ino); Inode* inode = fs->GetInode((uint32_t) msg->ino);
if ( !inode ) { RespondError(chl, errno); return; } if ( !inode ) { RespondError(chl, errno); return; }
inode->BeginWrite();
inode->data->i_atime = msg->times[0].tv_sec; inode->data->i_atime = msg->times[0].tv_sec;
inode->data->i_mtime = msg->times[1].tv_sec; inode->data->i_mtime = msg->times[1].tv_sec;
inode->Dirty(); inode->FinishWrite();
inode->Unref(); inode->Unref();
RespondSuccess(chl); RespondSuccess(chl);
} }
@ -1177,7 +1178,6 @@ int ext2_fuse_readdir(const char* /*path*/, void* buf, fuse_fill_dir_t filler,
if ( block ) if ( block )
block->Unref(); block->Unref();
inode->Sync();
inode->Unref(); inode->Unref();
return 0; return 0;
} }
@ -1192,9 +1192,10 @@ int ext2_fuse_utimens(const char* path, const struct timespec tv[2])
Inode* inode = ext2_fuse_resolve_path(path); Inode* inode = ext2_fuse_resolve_path(path);
if ( !inode ) if ( !inode )
return -errno; return -errno;
inode->BeginWrite();
inode->data->i_atime = tv[0].tv_sec; inode->data->i_atime = tv[0].tv_sec;
inode->data->i_mtime = tv[1].tv_sec; inode->data->i_mtime = tv[1].tv_sec;
inode->Dirty(); inode->FinishWrite();
inode->Unref(); inode->Unref();
return 0; return 0;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013. Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015.
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free
@ -64,10 +64,11 @@ Filesystem::Filesystem(Device* device)
clock_gettime(CLOCK_MONOTONIC, &now_monotonic); clock_gettime(CLOCK_MONOTONIC, &now_monotonic);
mtime_realtime = now_realtime.tv_sec; mtime_realtime = now_realtime.tv_sec;
mtime_monotonic = now_monotonic.tv_sec; mtime_monotonic = now_monotonic.tv_sec;
BeginWrite();
sb->s_mtime = mtime_realtime; sb->s_mtime = mtime_realtime;
sb->s_mnt_count++; sb->s_mnt_count++;
sb->s_state = EXT2_ERROR_FS; sb->s_state = EXT2_ERROR_FS;
Dirty(); FinishWrite();
Sync(); Sync();
} }
@ -79,16 +80,22 @@ Filesystem::~Filesystem()
for ( size_t i = 0; i < num_groups; i++ ) for ( size_t i = 0; i < num_groups; i++ )
delete block_groups[i]; delete block_groups[i];
delete[] block_groups; delete[] block_groups;
BeginWrite();
sb->s_state = EXT2_VALID_FS; sb->s_state = EXT2_VALID_FS;
Dirty(); FinishWrite();
Sync(); Sync();
sb_block->Unref(); sb_block->Unref();
} }
void Filesystem::Dirty() void Filesystem::BeginWrite()
{
sb_block->BeginWrite();
}
void Filesystem::FinishWrite()
{ {
dirty = true; dirty = true;
sb_block->Dirty(); sb_block->FinishWrite();
} }
void Filesystem::Sync() void Filesystem::Sync()
@ -185,8 +192,9 @@ uint32_t Filesystem::AllocateBlock(BlockGroup* preferred)
// rebuild all these values upon filesystem mount instead so we know // rebuild all these values upon filesystem mount instead so we know
// this can't happen. That also allows us to make the linked list // this can't happen. That also allows us to make the linked list
// requested above. // requested above.
BeginWrite();
sb->s_free_blocks_count--; sb->s_free_blocks_count--;
Dirty(); FinishWrite();
return errno = ENOSPC, 0; return errno = ENOSPC, 0;
} }
@ -206,8 +214,9 @@ uint32_t Filesystem::AllocateInode(BlockGroup* preferred)
// rebuild all these values upon filesystem mount instead so we know // rebuild all these values upon filesystem mount instead so we know
// this can't happen. That also allows us to make the linked list // this can't happen. That also allows us to make the linked list
// requested above. // requested above.
BeginWrite();
sb->s_free_inodes_count--; sb->s_free_inodes_count--;
Dirty(); FinishWrite();
return errno = ENOSPC, 0; return errno = ENOSPC, 0;
} }

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013. Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015.
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free
@ -60,7 +60,8 @@ public:
uint32_t AllocateInode(BlockGroup* preferred = NULL); uint32_t AllocateInode(BlockGroup* preferred = NULL);
void FreeBlock(uint32_t block_id); void FreeBlock(uint32_t block_id);
void FreeInode(uint32_t inode_id); void FreeInode(uint32_t inode_id);
void Dirty(); void BeginWrite();
void FinishWrite();
void Sync(); void Sync();
}; };

View File

@ -82,9 +82,10 @@ uint32_t Inode::Mode()
void Inode::SetMode(uint32_t mode) void Inode::SetMode(uint32_t mode)
{ {
BeginWrite();
// TODO: Use i_mode_high. // TODO: Use i_mode_high.
data->i_mode = (uint16_t) mode; data->i_mode = (uint16_t) mode;
Dirty(); FinishWrite();
} }
uint32_t Inode::UserId() uint32_t Inode::UserId()
@ -95,9 +96,10 @@ uint32_t Inode::UserId()
void Inode::SetUserId(uint32_t user) void Inode::SetUserId(uint32_t user)
{ {
BeginWrite();
// TODO: Use i_uid_high. // TODO: Use i_uid_high.
data->i_uid = (uint16_t) user; data->i_uid = (uint16_t) user;
Dirty(); FinishWrite();
} }
uint32_t Inode::GroupId() uint32_t Inode::GroupId()
@ -108,9 +110,10 @@ uint32_t Inode::GroupId()
void Inode::SetGroupId(uint32_t group) void Inode::SetGroupId(uint32_t group)
{ {
BeginWrite();
// TODO: Use i_gid_high. // TODO: Use i_gid_high.
data->i_gid = (uint16_t) group; data->i_gid = (uint16_t) group;
Dirty(); FinishWrite();
} }
uint64_t Inode::Size() uint64_t Inode::Size()
@ -150,24 +153,28 @@ void Inode::SetSize(uint64_t new_size)
actual_blocks += divup(logical_blocks - max_singly, ENTRIES * ENTRIES); actual_blocks += divup(logical_blocks - max_singly, ENTRIES * ENTRIES);
if ( max_doubly <= logical_blocks ) if ( max_doubly <= logical_blocks )
actual_blocks += divup(logical_blocks - max_doubly, ENTRIES * ENTRIES * ENTRIES); actual_blocks += divup(logical_blocks - max_doubly, ENTRIES * ENTRIES * ENTRIES);
data->i_blocks = (actual_blocks * filesystem->block_size) / 512;
BeginWrite();
data->i_blocks = (actual_blocks * filesystem->block_size) / 512;
if ( EXT2_S_ISREG(data->i_mode) && largefile ) if ( EXT2_S_ISREG(data->i_mode) && largefile )
data->i_dir_acl = upper; data->i_dir_acl = upper;
Dirty(); FinishWrite();
Modified(); Modified();
} }
void Inode::Linked() void Inode::Linked()
{ {
BeginWrite();
data->i_links_count++; data->i_links_count++;
Dirty(); FinishWrite();
} }
void Inode::Unlinked() void Inode::Unlinked()
{ {
BeginWrite();
data->i_links_count--; data->i_links_count--;
Dirty(); FinishWrite();
} }
Block* Inode::GetBlockFromTable(Block* table, uint32_t index) Block* Inode::GetBlockFromTable(Block* table, uint32_t index)
@ -182,8 +189,9 @@ Block* Inode::GetBlockFromTable(Block* table, uint32_t index)
if ( block_id ) if ( block_id )
{ {
Block* block = filesystem->device->GetBlockZeroed(block_id); Block* block = filesystem->device->GetBlockZeroed(block_id);
table->BeginWrite();
((uint32_t*) table->block_data)[index] = block_id; ((uint32_t*) table->block_data)[index] = block_id;
table->Dirty(); table->FinishWrite();
return block; return block;
} }
return NULL; return NULL;
@ -276,6 +284,7 @@ bool Inode::FreeIndirect(uint64_t from, uint64_t offset, uint32_t block_id,
Block* block = filesystem->device->GetBlock(block_id); Block* block = filesystem->device->GetBlock(block_id);
uint32_t* table = (uint32_t*) block->block_data; uint32_t* table = (uint32_t*) block->block_data;
bool any_children = false; bool any_children = false;
bool begun_writing = false;
for ( uint64_t i = 0; i < ENTRIES; i++ ) for ( uint64_t i = 0; i < ENTRIES; i++ )
{ {
if ( !table[i] ) if ( !table[i] )
@ -290,9 +299,15 @@ bool Inode::FreeIndirect(uint64_t from, uint64_t offset, uint32_t block_id,
continue; continue;
} }
filesystem->FreeBlock(table[i]); filesystem->FreeBlock(table[i]);
if ( !begun_writing )
{
block->BeginWrite();
begun_writing = true;
}
table[i] = 0; table[i] = 0;
block->Dirty();
} }
if ( begun_writing )
block->FinishWrite();
return any_children; return any_children;
} }
@ -319,8 +334,9 @@ void Inode::Truncate(uint64_t new_size)
{ {
Block* partial_block = GetBlock(new_num_blocks-1); Block* partial_block = GetBlock(new_num_blocks-1);
uint8_t* data = partial_block->block_data; uint8_t* data = partial_block->block_data;
partial_block->BeginWrite();
memset(data + partial, 0, filesystem->block_size - partial); memset(data + partial, 0, filesystem->block_size - partial);
partial_block->Dirty(); partial_block->FinishWrite();
} }
const uint64_t ENTRIES = filesystem->block_size / sizeof(uint32_t); const uint64_t ENTRIES = filesystem->block_size / sizeof(uint32_t);
@ -333,6 +349,8 @@ void Inode::Truncate(uint64_t new_size)
uint64_t max_doubly = max_singly + block_doubly; uint64_t max_doubly = max_singly + block_doubly;
uint64_t max_triply = max_doubly + block_triply; uint64_t max_triply = max_doubly + block_triply;
BeginWrite();
for ( uint64_t i = new_num_blocks; i < old_num_blocks && i < 12; i++ ) for ( uint64_t i = new_num_blocks; i < old_num_blocks && i < 12; i++ )
{ {
filesystem->FreeBlock(data->i_block[i]); filesystem->FreeBlock(data->i_block[i]);
@ -359,7 +377,7 @@ void Inode::Truncate(uint64_t new_size)
(void) max_triply; (void) max_triply;
Dirty(); FinishWrite();
} }
Inode* Inode::Open(const char* elem, int flags, mode_t mode) Inode* Inode::Open(const char* elem, int flags, mode_t mode)
@ -520,6 +538,8 @@ bool Inode::Link(const char* elem, Inode* dest, bool directories)
if ( !block && !(block = GetBlock(block_id = hole_block_id)) ) if ( !block && !(block = GetBlock(block_id = hole_block_id)) )
return NULL; return NULL;
block->BeginWrite();
uint8_t* block_data = block->block_data + hole_block_offset; uint8_t* block_data = block->block_data + hole_block_offset;
struct ext_dirent* entry = (struct ext_dirent*) block_data; struct ext_dirent* entry = (struct ext_dirent*) block_data;
@ -528,7 +548,6 @@ bool Inode::Link(const char* elem, Inode* dest, bool directories)
{ {
entry->reclen = roundup(sizeof(struct ext_dirent) + entry->name_len, (size_t) 4); entry->reclen = roundup(sizeof(struct ext_dirent) + entry->name_len, (size_t) 4);
assert(entry->reclen); assert(entry->reclen);
// Block marked dirty below.
block_data += entry->reclen; block_data += entry->reclen;
entry = (struct ext_dirent*) block_data; entry = (struct ext_dirent*) block_data;
} }
@ -544,7 +563,7 @@ bool Inode::Link(const char* elem, Inode* dest, bool directories)
assert(entry->reclen); assert(entry->reclen);
block->Dirty(); block->FinishWrite();
dest->Linked(); dest->Linked();
@ -610,6 +629,9 @@ Inode* Inode::Unlink(const char* elem, bool directories, bool force)
} }
inode->Unlinked(); inode->Unlinked();
block->BeginWrite();
entry->inode = 0; entry->inode = 0;
entry->name_len = 0; entry->name_len = 0;
entry->file_type = 0; entry->file_type = 0;
@ -628,7 +650,6 @@ Inode* Inode::Unlink(const char* elem, bool directories, bool force)
strncpy(entry->name + entry->name_len, "", strncpy(entry->name + entry->name_len, "",
entry->reclen - sizeof(struct ext_dirent) - entry->name_len); entry->reclen - sizeof(struct ext_dirent) - entry->name_len);
assert(entry->reclen); assert(entry->reclen);
block->Dirty();
// If the entire block is empty, we'll need to remove it. // If the entire block is empty, we'll need to remove it.
if ( !entry->name[0] && entry->reclen == block_size ) if ( !entry->name[0] && entry->reclen == block_size )
@ -641,12 +662,13 @@ Inode* Inode::Unlink(const char* elem, bool directories, bool force)
{ {
Block* last_block = GetBlock(num_blocks-1); Block* last_block = GetBlock(num_blocks-1);
memcpy(block->block_data, last_block->block_data, block_size); memcpy(block->block_data, last_block->block_data, block_size);
block->Dirty();
last_block->Unref(); last_block->Unref();
} }
Truncate(filesize - block_size); Truncate(filesize - block_size);
} }
block->FinishWrite();
block->Unref(); block->Unref();
return inode; return inode;
@ -733,8 +755,9 @@ ssize_t Inode::WriteAt(const uint8_t* buf, size_t s_count, off_t o_offset)
if ( !block ) if ( !block )
return sofar ? sofar : -1; return sofar ? sofar : -1;
size_t amount = count - sofar < block_left ? count - sofar : block_left; size_t amount = count - sofar < block_left ? count - sofar : block_left;
block->BeginWrite();
memcpy(block->block_data + block_offset, buf + sofar, amount); memcpy(block->block_data + block_offset, buf + sofar, amount);
block->Dirty(); block->FinishWrite();
sofar += amount; sofar += amount;
offset += amount; offset += amount;
block->Unref(); block->Unref();
@ -835,8 +858,9 @@ Inode* Inode::CreateDirectory(const char* path, mode_t mode)
uint32_t group_id = (result->inode_id - 1) / filesystem->sb->s_inodes_per_group; uint32_t group_id = (result->inode_id - 1) / filesystem->sb->s_inodes_per_group;
assert(group_id < filesystem->num_groups); assert(group_id < filesystem->num_groups);
BlockGroup* block_group = filesystem->GetBlockGroup(group_id); BlockGroup* block_group = filesystem->GetBlockGroup(group_id);
block_group->BeginWrite();
block_group->data->bg_used_dirs_count++; block_group->data->bg_used_dirs_count++;
block_group->Dirty(); block_group->FinishWrite();
block_group->Unref(); block_group->Unref();
struct timespec now; struct timespec now;
@ -886,8 +910,9 @@ bool Inode::RemoveDirectory(const char* path)
uint32_t group_id = (result->inode_id - 1) / filesystem->sb->s_inodes_per_group; uint32_t group_id = (result->inode_id - 1) / filesystem->sb->s_inodes_per_group;
assert(group_id < filesystem->num_groups); assert(group_id < filesystem->num_groups);
BlockGroup* block_group = filesystem->GetBlockGroup(group_id); BlockGroup* block_group = filesystem->GetBlockGroup(group_id);
block_group->BeginWrite();
block_group->data->bg_used_dirs_count--; block_group->data->bg_used_dirs_count--;
block_group->Dirty(); block_group->FinishWrite();
block_group->Unref(); block_group->Unref();
result->Unref(); result->Unref();
@ -939,13 +964,14 @@ void Inode::Delete()
Truncate(0); Truncate(0);
uint32_t deleted_inode_id = inode_id; uint32_t deleted_inode_id = inode_id;
memset(data, 0, sizeof(*data));
struct timespec now; struct timespec now;
clock_gettime(CLOCK_REALTIME, &now); clock_gettime(CLOCK_REALTIME, &now);
data->i_dtime = now.tv_sec;
Dirty();
delete this; BeginWrite();
memset(data, 0, sizeof(*data));
data->i_dtime = now.tv_sec;
FinishWrite();
filesystem->FreeInode(deleted_inode_id); filesystem->FreeInode(deleted_inode_id);
} }
@ -962,8 +988,7 @@ void Inode::Unref()
{ {
if ( !data->i_links_count ) if ( !data->i_links_count )
Delete(); Delete();
else delete this;
delete this;
} }
} }
@ -979,8 +1004,7 @@ void Inode::RemoteUnref()
{ {
if ( !data->i_links_count ) if ( !data->i_links_count )
Delete(); Delete();
else delete this;
delete this;
} }
} }
@ -988,11 +1012,17 @@ void Inode::Modified()
{ {
struct timespec now; struct timespec now;
clock_gettime(CLOCK_REALTIME, &now); clock_gettime(CLOCK_REALTIME, &now);
BeginWrite();
data->i_mtime = now.tv_sec; data->i_mtime = now.tv_sec;
Dirty(); FinishWrite();
} }
void Inode::Dirty() void Inode::BeginWrite()
{
data_block->BeginWrite();
}
void Inode::FinishWrite()
{ {
struct timespec now; struct timespec now;
clock_gettime(CLOCK_REALTIME, &now); clock_gettime(CLOCK_REALTIME, &now);
@ -1006,7 +1036,7 @@ void Inode::Dirty()
next_dirty->prev_dirty = this; next_dirty->prev_dirty = this;
filesystem->dirty_inode = this; filesystem->dirty_inode = this;
} }
data_block->Dirty(); data_block->FinishWrite();
Use(); Use();
} }
@ -1015,6 +1045,7 @@ void Inode::Sync()
if ( !dirty ) if ( !dirty )
return; return;
data_block->Sync(); data_block->Sync();
// TODO: The inode contents needs to be sync'd as well!
(prev_dirty ? prev_dirty->next_dirty : filesystem->dirty_inode) = next_dirty; (prev_dirty ? prev_dirty->next_dirty : filesystem->dirty_inode) = next_dirty;
if ( next_dirty ) if ( next_dirty )
next_dirty->prev_dirty = prev_dirty; next_dirty->prev_dirty = prev_dirty;

View File

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2013. Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015.
This program is free software: you can redistribute it and/or modify it This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free under the terms of the GNU General Public License as published by the Free
@ -76,7 +76,8 @@ public:
void RemoteRefer(); void RemoteRefer();
void RemoteUnref(); void RemoteUnref();
void Sync(); void Sync();
void Dirty(); void BeginWrite();
void FinishWrite();
void Modified(); void Modified();
void Use(); void Use();
void Unlink(); void Unlink();