Fix extfs reference counts.

This commit is contained in:
Jonas 'Sortie' Termansen 2015-07-08 22:38:40 +02:00
parent 21c82e4467
commit 5deb51eeae
5 changed files with 40 additions and 21 deletions

View File

@ -68,6 +68,10 @@ BlockGroup::BlockGroup(Filesystem* filesystem, uint32_t group_id)
BlockGroup::~BlockGroup()
{
Sync();
if ( block_bitmap_chunk )
block_bitmap_chunk->Unref();
if ( inode_bitmap_chunk )
inode_bitmap_chunk->Unref();
if ( data_block )
data_block->Unref();
filesystem->block_groups[group_id] = NULL;

View File

@ -171,7 +171,10 @@ void HandleRefer(int chl, struct fsm_req_refer* msg, Filesystem* fs)
if ( fs->num_inodes <= msg->ino )
return;
if ( Inode* inode = fs->GetInode((uint32_t) msg->ino) )
{
inode->RemoteRefer();
inode->Unref();
}
}
void HandleUnref(int chl, struct fsm_req_unref* msg, Filesystem* fs)
@ -180,7 +183,10 @@ void HandleUnref(int chl, struct fsm_req_unref* msg, Filesystem* fs)
if ( fs->num_inodes <= msg->ino )
return;
if ( Inode* inode = fs->GetInode((uint32_t) msg->ino) )
{
inode->RemoteUnref();
inode->Unref();
}
}
void HandleSync(int chl, struct fsm_req_sync* msg, Filesystem* fs)
@ -410,6 +416,7 @@ void HandleReadDir(int chl, struct fsm_req_readdirents* msg, Filesystem* fs)
}
if ( block )
block->Unref();
inode->Unref();
kernel_entry.d_reclen = sizeof(kernel_entry);
RespondReadDir(chl, &kernel_entry);
@ -441,18 +448,16 @@ void HandleUnlink(int chl, struct fsm_req_unlink* msg, Filesystem* fs)
memcpy(path, pathraw, msg->namelen);
path[msg->namelen] = '\0';
Inode* result = inode->Unlink(path, false);
bool result = inode->Unlink(path, false);
free(path);
inode->Unref();
if ( !result ) { RespondError(chl, errno); return; }
result->Unref();
RespondSuccess(chl);
}
void HandleRemoveDir(int chl, struct fsm_req_unlink* msg, Filesystem* fs)
void HandleRemoveDir(int chl, struct fsm_req_rmdir* msg, Filesystem* fs)
{
if ( fs->num_inodes <= msg->dirino ) { RespondError(chl, EBADF); return; }
Inode* inode = fs->GetInode((uint32_t) msg->dirino);
@ -772,6 +777,7 @@ int fsmarshall_main(const char* argv0,
{
fprintf(stderr, "%s: filesystem server shutting down, syncing...", argv0);
fflush(stderr);
// TODO: Need to close all open inodes here, and in the fuse backend too.
fs->Sync();
fprintf(stderr, " done.\n");
}

View File

@ -82,7 +82,7 @@ Inode* ext2_fuse_resolve_path(const char* path)
if ( *path == '/' )
{
if ( !EXT2_S_ISDIR(inode->Mode()) )
return errno = ENOTDIR, (Inode*) NULL;
return inode->Unref(), errno = ENOTDIR, (Inode*) NULL;
path++;
continue;
}
@ -113,7 +113,7 @@ Inode* ext2_fuse_parent_dir(const char** path_ptr)
if ( *path == '/' )
{
if ( !EXT2_S_ISDIR(inode->Mode()) )
return errno = ENOTDIR, (Inode*) NULL;
return inode->Unref(), errno = ENOTDIR, (Inode*) NULL;
path++;
continue;
}
@ -199,11 +199,10 @@ int ext2_fuse_unlink(const char* path)
Inode* inode = ext2_fuse_parent_dir(&path);
if ( !inode )
return -errno;
Inode* result = inode->Unlink(path, false);
bool result = inode->Unlink(path, false);
inode->Unref();
if ( !result )
return -errno;
result->Unref();
return 0;
}
@ -344,6 +343,7 @@ int ext2_fuse_create(const char* path, mode_t mode, struct fuse_file_info* fi)
return -errno;
fi->fh = (uint64_t) result->inode_id;
fi->keep_cache = 1;
result->RemoteRefer();
result->Unref();
return 0;
}

View File

@ -61,7 +61,7 @@ Inode::Inode(Filesystem* filesystem, uint32_t inode_id)
this->data = NULL;
this->filesystem = filesystem;
this->reference_count = 1;
this->remote_reference_count = 1;
this->remote_reference_count = 0;
this->inode_id = inode_id;
this->dirty = false;
}
@ -274,6 +274,7 @@ Block* Inode::GetBlock(uint64_t offset)
goto read_doubly;
}
table->Unref();
return NULL;
}
@ -595,7 +596,7 @@ bool Inode::Link(const char* elem, Inode* dest, bool directories)
return true;
}
Inode* Inode::Unlink(const char* elem, bool directories, bool force)
Inode* Inode::UnlinkKeep(const char* elem, bool directories, bool force)
{
if ( !EXT2_S_ISDIR(Mode()) )
return errno = ENOTDIR, (Inode*) NULL;
@ -701,6 +702,15 @@ Inode* Inode::Unlink(const char* elem, bool directories, bool force)
return errno = ENOENT, (Inode*) NULL;
}
bool Inode::Unlink(const char* elem, bool directories, bool force)
{
Inode* result = UnlinkKeep(elem, directories, force);
if ( !result )
return false;
result->Unref();
return true;
}
ssize_t Inode::ReadAt(uint8_t* buf, size_t s_count, off_t o_offset)
{
if ( !EXT2_S_ISREG(Mode()) && !EXT2_S_ISLNK(Mode()) )
@ -925,24 +935,20 @@ Inode* Inode::CreateDirectory(const char* path, mode_t mode)
if ( !Link(path, result, true) )
{
error:
result->Truncate(0);
memset(result->data, 0, sizeof(*result->data));
// TODO: dtime
result->Unref();
filesystem->FreeInode(result_inode_id);
return NULL;
}
if ( !result->Link(".", result, true) )
{
Unlink(path, true);
Unlink(path, true, true);
goto error;
}
if ( !result->Link("..", this, true) )
{
result->Unlink(".", true);
Unlink(path, true);
result->Unlink(".", true, true);
Unlink(path, true, true);
goto error;
}
@ -951,11 +957,11 @@ Inode* Inode::CreateDirectory(const char* path, mode_t mode)
bool Inode::RemoveDirectory(const char* path)
{
Inode* result = Unlink(path, true);
Inode* result = UnlinkKeep(path, true);
if ( !result )
return false;
result->Unlink("..", true);
result->Unlink(".", true);
result->Unlink("..", true, true);
result->Unlink(".", true, true);
result->Truncate(0);
// Decrease the directory count statistics.
@ -1035,6 +1041,7 @@ void Inode::Refer()
void Inode::Unref()
{
assert(0 < reference_count);
reference_count--;
if ( !reference_count && !remote_reference_count )
{
@ -1051,6 +1058,7 @@ void Inode::RemoteRefer()
void Inode::RemoteUnref()
{
assert(0 < remote_reference_count);
remote_reference_count--;
if ( !reference_count && !remote_reference_count )
{

View File

@ -64,7 +64,8 @@ public:
Inode* Open(const char* elem, int flags, mode_t mode);
bool Link(const char* elem, Inode* dest, bool directories);
bool Symlink(const char* elem, const char* dest);
Inode* Unlink(const char* elem, bool directories, bool force=false);
bool Unlink(const char* elem, bool directories, bool force=false);
Inode* UnlinkKeep(const char* elem, bool directories, bool force=false);
ssize_t ReadAt(uint8_t* buffer, size_t count, off_t offset);
ssize_t WriteAt(const uint8_t* buffer, size_t count, off_t offset);
bool UnembedInInode();