mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 13:45:07 +00:00
Kernel/Ext2: Check and set file system state
This is supposed to detect whether a file system was unmounted cleanly or not.
This commit is contained in:
parent
8fb126bec6
commit
251b17085b
2 changed files with 30 additions and 3 deletions
|
@ -65,6 +65,9 @@ ErrorOr<void> Ext2FS::initialize_while_locked()
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (super_block.s_state == EXT2_ERROR_FS)
|
||||||
|
dmesgln("Ext2FS: Was not unmounted cleanly, file system may be erroneous!");
|
||||||
|
|
||||||
if constexpr (EXT2_DEBUG) {
|
if constexpr (EXT2_DEBUG) {
|
||||||
dmesgln("Ext2FS: {} inodes, {} blocks", super_block.s_inodes_count, super_block.s_blocks_count);
|
dmesgln("Ext2FS: {} inodes, {} blocks", super_block.s_inodes_count, super_block.s_blocks_count);
|
||||||
dmesgln("Ext2FS: Block size: {}", EXT2_BLOCK_SIZE(&super_block));
|
dmesgln("Ext2FS: Block size: {}", EXT2_BLOCK_SIZE(&super_block));
|
||||||
|
@ -105,6 +108,12 @@ ErrorOr<void> Ext2FS::initialize_while_locked()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_root_inode = TRY(build_root_inode());
|
m_root_inode = TRY(build_root_inode());
|
||||||
|
|
||||||
|
// Set filesystem to "error" state until we unmount cleanly.
|
||||||
|
dmesgln("Ext2FS: Mount successful, setting superblock to error state.");
|
||||||
|
m_super_block.s_state = EXT2_ERROR_FS;
|
||||||
|
TRY(flush_super_block());
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,16 +543,33 @@ unsigned Ext2FS::free_inode_count() const
|
||||||
|
|
||||||
ErrorOr<void> Ext2FS::prepare_to_clear_last_mount(Inode& mount_guest_inode)
|
ErrorOr<void> Ext2FS::prepare_to_clear_last_mount(Inode& mount_guest_inode)
|
||||||
{
|
{
|
||||||
(void)mount_guest_inode;
|
|
||||||
MutexLocker locker(m_lock);
|
MutexLocker locker(m_lock);
|
||||||
|
bool any_inode_busy = false;
|
||||||
for (auto& it : m_inode_cache) {
|
for (auto& it : m_inode_cache) {
|
||||||
if (it.value->ref_count() > 1)
|
// We hold the last reference to the root inode, and the VFS Mount object holds the last reference to the mount_guest_inode,
|
||||||
return EBUSY;
|
// so they are allowed to have one more reference.
|
||||||
|
if ((it.value == m_root_inode || it.value->identifier() == mount_guest_inode.identifier()) && it.value->ref_count() > 2) {
|
||||||
|
dbgln_if(EXT2_DEBUG, "Ext2FS: Ignoring root or mount point inode's last reference");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// The Inode::all_instances list always holds one reference to all inodes, which we disregard.
|
||||||
|
if (it.value->ref_count() > 1) {
|
||||||
|
dbgln_if(EXT2_DEBUG, "Ext2FS: Busy inode {} ({} refs)", it.value->index(), it.value->ref_count());
|
||||||
|
any_inode_busy = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (any_inode_busy)
|
||||||
|
return EBUSY;
|
||||||
|
|
||||||
BlockBasedFileSystem::remove_disk_cache_before_last_unmount();
|
BlockBasedFileSystem::remove_disk_cache_before_last_unmount();
|
||||||
m_inode_cache.clear();
|
m_inode_cache.clear();
|
||||||
m_root_inode = nullptr;
|
m_root_inode = nullptr;
|
||||||
|
|
||||||
|
// Mark filesystem as valid before unmount.
|
||||||
|
dmesgln("Ext2FS: Clean unmount, setting superblock to valid state");
|
||||||
|
m_super_block.s_state = EXT2_VALID_FS;
|
||||||
|
TRY(flush_super_block());
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ FileSystem::~FileSystem()
|
||||||
ErrorOr<void> FileSystem::prepare_to_unmount(Inode& mount_guest_inode)
|
ErrorOr<void> FileSystem::prepare_to_unmount(Inode& mount_guest_inode)
|
||||||
{
|
{
|
||||||
return m_attach_count.with([&](auto& attach_count) -> ErrorOr<void> {
|
return m_attach_count.with([&](auto& attach_count) -> ErrorOr<void> {
|
||||||
|
dbgln_if(VFS_DEBUG, "VFS: File system {} (id {}) is attached {} time(s)", class_name(), m_fsid.value(), attach_count);
|
||||||
if (attach_count == 1)
|
if (attach_count == 1)
|
||||||
return prepare_to_clear_last_mount(mount_guest_inode);
|
return prepare_to_clear_last_mount(mount_guest_inode);
|
||||||
return {};
|
return {};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue