diff --git a/Kernel/FileSystem/Custody.cpp b/Kernel/FileSystem/Custody.cpp index 70bcd8e315..f70d1a2719 100644 --- a/Kernel/FileSystem/Custody.cpp +++ b/Kernel/FileSystem/Custody.cpp @@ -12,6 +12,35 @@ static Lockable>& all_custodies() return *table; } +Custody* Custody::get_if_cached(Custody* parent, const String& name) +{ + LOCKER(all_custodies().lock()); + for (auto& custody : all_custodies().resource()) { + if (custody->is_deleted()) + continue; + if (custody->is_mounted_on()) + continue; + if (custody->parent() == parent && custody->name() == name) + return custody; + } + return nullptr; +} + +Retained Custody::get_or_create(Custody* parent, const String& name, Inode& inode) +{ + if (RetainPtr cached_custody = get_if_cached(parent, name)) { + if (&cached_custody->inode() != &inode) { + dbgprintf("WTF! cached custody for name '%s' has inode=%s, new inode=%s\n", + name.characters(), + cached_custody->inode().identifier().to_string().characters(), + inode.identifier().to_string().characters()); + } + ASSERT(&cached_custody->inode() == &inode); + return *cached_custody; + } + return create(parent, name, inode); +} + Custody::Custody(Custody* parent, const String& name, Inode& inode) : m_parent(parent) , m_name(name) @@ -39,3 +68,19 @@ String Custody::absolute_path() const } return builder.to_string(); } + +void Custody::did_delete(Badge) +{ + m_deleted = true; +} + +void Custody::did_mount_on(Badge) +{ + m_mounted_on = true; +} + +void Custody::did_rename(Badge, const String& name) +{ + m_name = name; +} + diff --git a/Kernel/FileSystem/Custody.h b/Kernel/FileSystem/Custody.h index a468e4cf98..9de3d93dd8 100644 --- a/Kernel/FileSystem/Custody.h +++ b/Kernel/FileSystem/Custody.h @@ -1,13 +1,19 @@ #pragma once #include +#include #include #include class Inode; +class VFS; + +// FIXME: Custody needs some locking. class Custody : public Retainable { public: + static Custody* get_if_cached(Custody* parent, const String& name); + static Retained get_or_create(Custody* parent, const String& name, Inode&); static Retained create(Custody* parent, const String& name, Inode& inode) { return adopt(*new Custody(parent, name, inode)); @@ -17,18 +23,24 @@ public: Custody* parent() { return m_parent.ptr(); } const Custody* parent() const { return m_parent.ptr(); } - Inode& inode() { return *m_inode; } const Inode& inode() const { return *m_inode; } - const String& name() const { return m_name; } - String absolute_path() const; + bool is_deleted() const { return m_deleted; } + bool is_mounted_on() const { return m_mounted_on; } + + void did_delete(Badge); + void did_mount_on(Badge); + void did_rename(Badge, const String& name); + private: Custody(Custody* parent, const String& name, Inode&); RetainPtr m_parent; String m_name; Retained m_inode; + bool m_deleted { false }; + bool m_mounted_on { false }; }; diff --git a/Kernel/FileSystem/InodeIdentifier.h b/Kernel/FileSystem/InodeIdentifier.h index 95c1bc6226..d6d4c4e881 100644 --- a/Kernel/FileSystem/InodeIdentifier.h +++ b/Kernel/FileSystem/InodeIdentifier.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -35,6 +36,8 @@ public: bool is_root_inode() const; + String to_string() const { return String::format("%u:%u", m_fsid, m_index); } + private: dword m_fsid { 0 }; dword m_index { 0 }; diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index e5f6ad5116..c977c03932 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -48,6 +48,8 @@ bool VFS::mount(Retained&& file_system, StringView path) // FIXME: check that this is not already a mount point auto mount = make(*result.value(), move(file_system)); m_mounts.append(move(mount)); + + result.value()->did_mount_on({}); return true; } @@ -368,6 +370,8 @@ KResult VFS::rename(StringView old_path, StringView new_path, Custody& base) return KResult(-EACCES); } + auto new_basename = FileSystemPath(new_path).basename(); + if (!new_custody_or_error.is_error()) { auto& new_custody = *new_custody_or_error.value(); auto& new_inode = new_custody.inode(); @@ -380,18 +384,20 @@ KResult VFS::rename(StringView old_path, StringView new_path, Custody& base) } if (new_inode.is_directory() && !old_inode.is_directory()) return KResult(-EISDIR); - auto result = new_parent_inode.remove_child(FileSystemPath(new_path).basename()); + auto result = new_parent_inode.remove_child(new_basename); if (result.is_error()) return result; + new_custody.did_delete({}); } - auto result = new_parent_inode.add_child(old_inode.identifier(), FileSystemPath(new_path).basename(), 0 /* FIXME: file type? */); + auto result = new_parent_inode.add_child(old_inode.identifier(), new_basename, 0 /* FIXME: file type? */); if (result.is_error()) return result; result = old_parent_inode.remove_child(FileSystemPath(old_path).basename()); if (result.is_error()) return result; + old_custody.did_rename({}, new_basename); return KSuccess; } @@ -479,7 +485,12 @@ KResult VFS::unlink(StringView path, Custody& base) return KResult(-EACCES); } - return parent_inode.remove_child(FileSystemPath(path).basename()); + auto result = parent_inode.remove_child(FileSystemPath(path).basename()); + if (result.is_error()) + return result; + + custody.did_delete({}); + return KSuccess; } KResult VFS::symlink(StringView target, StringView linkpath, Custody& base) @@ -662,7 +673,7 @@ KResultOr> VFS::resolve_path_to_custody(StringView path, Custo crumb_inode = get_inode(crumb_id); ASSERT(crumb_inode); - custody_chain.append(Custody::create(custody_chain.last().ptr(), part, *crumb_inode)); + custody_chain.append(Custody::get_or_create(custody_chain.last().ptr(), part, *crumb_inode)); metadata = crumb_inode->metadata(); if (metadata.is_directory()) {