mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Fix extfs reference counts.
This commit is contained in:
parent
21c82e4467
commit
5deb51eeae
5 changed files with 40 additions and 21 deletions
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue