diff options
author | Sergey Bugaev <bugaevc@gmail.com> | 2019-08-16 16:35:02 +0300 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-08-17 12:07:55 +0200 |
commit | 37cc80fb965304319f5c5a56c047fed82e4e16ed (patch) | |
tree | ecbdfe5458fe3abd8b0d2fd252e162dd4a9159a6 /Kernel | |
parent | 1febd59f830d0c5ee240b73c7fd376c18f76f754 (diff) | |
download | serenity-37cc80fb965304319f5c5a56c047fed82e4e16ed.zip |
ProcFS: Do not assume there is one of it
The complication is around /proc/sys/ variables, which were attached
to inodes. Now they're their own thing, and the corresponding inodes
are lazily created (as all other ProcFS inodes are) and simply refer
to them by index.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Devices/PATAChannel.cpp | 2 | ||||
-rw-r--r-- | Kernel/FileSystem/ProcFS.cpp | 254 | ||||
-rw-r--r-- | Kernel/FileSystem/ProcFS.h | 19 | ||||
-rw-r--r-- | Kernel/init.cpp | 4 |
4 files changed, 144 insertions, 135 deletions
diff --git a/Kernel/Devices/PATAChannel.cpp b/Kernel/Devices/PATAChannel.cpp index 60e0f469cc..df3481a5ae 100644 --- a/Kernel/Devices/PATAChannel.cpp +++ b/Kernel/Devices/PATAChannel.cpp @@ -99,7 +99,7 @@ PATAChannel::PATAChannel(ChannelType type) , m_io_base((type == ChannelType::Primary ? 0x1F0 : 0x170)) { m_dma_enabled.resource() = true; - ProcFS::the().add_sys_bool("ide_dma", m_dma_enabled); + ProcFS::add_sys_bool("ide_dma", m_dma_enabled); initialize(); detect_disks(); diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 39ecf27337..5b18c989e6 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -53,6 +53,8 @@ enum ProcFileType { FI_Root_net, // directory __FI_Root_End, + FI_Root_sys_variable, + FI_Root_net_adapters, FI_Root_net_tcp, FI_Root_net_udp, @@ -87,6 +89,11 @@ static inline ProcParentDirectory to_proc_parent_directory(const InodeIdentifier return (ProcParentDirectory)((identifier.index() >> 12) & 0xf); } +static inline ProcFileType to_proc_file_type(const InodeIdentifier& identifier) +{ + return (ProcFileType)(identifier.index() & 0xff); +} + static inline int to_fd(const InodeIdentifier& identifier) { ASSERT(to_proc_parent_directory(identifier) == PDI_PID_fd); @@ -96,7 +103,8 @@ static inline int to_fd(const InodeIdentifier& identifier) static inline int to_sys_index(const InodeIdentifier& identifier) { ASSERT(to_proc_parent_directory(identifier) == PDI_Root_sys); - return identifier.index() & 0xff; + ASSERT(to_proc_file_type(identifier) == FI_Root_sys_variable); + return identifier.index() >> 16u; } static inline InodeIdentifier to_identifier(unsigned fsid, ProcParentDirectory parent, pid_t pid, ProcFileType proc_file_type) @@ -112,7 +120,7 @@ static inline InodeIdentifier to_identifier_with_fd(unsigned fsid, pid_t pid, in static inline InodeIdentifier sys_var_to_identifier(unsigned fsid, unsigned index) { ASSERT(index < 256); - return { fsid, (PDI_Root_sys << 12u) | index }; + return { fsid, (PDI_Root_sys << 12u) | (index << 16u) | FI_Root_sys_variable }; } static inline InodeIdentifier to_parent_id(const InodeIdentifier& identifier) @@ -140,11 +148,6 @@ static inline u8 to_unused_metadata(const InodeIdentifier& identifier) } #endif -static inline ProcFileType to_proc_file_type(const InodeIdentifier& identifier) -{ - return (ProcFileType)(identifier.index() & 0xff); -} - static inline bool is_process_related_file(const InodeIdentifier& identifier) { if (to_proc_file_type(identifier) == FI_PID) @@ -179,14 +182,6 @@ static inline bool is_persistent_inode(const InodeIdentifier& identifier) return to_proc_parent_directory(identifier) == PDI_Root_sys; } -static ProcFS* s_the; - -ProcFS& ProcFS::the() -{ - ASSERT(s_the); - return *s_the; -} - NonnullRefPtr<ProcFS> ProcFS::create() { return adopt(*new ProcFS); @@ -639,31 +634,54 @@ Optional<KBuffer> procfs$inodes(InodeIdentifier) return builder.build(); } -struct SysVariableData final : public ProcFSInodeCustomData { - virtual ~SysVariableData() override {} - - enum Type { +struct SysVariable { + String name; + enum class Type : u8 { Invalid, Boolean, String, }; - Type type { Invalid }; + Type type { Type::Invalid }; Function<void()> notify_callback; - void* address; + void* address { nullptr }; + + static SysVariable& for_inode(InodeIdentifier); + + void notify() + { + if (notify_callback) + notify_callback(); + } }; +static Vector<SysVariable, 16>* s_sys_variables; + +static inline Vector<SysVariable, 16>& sys_variables() +{ + if (s_sys_variables == nullptr) { + s_sys_variables = new Vector<SysVariable, 16>; + s_sys_variables->append({ "", SysVariable::Type::Invalid, nullptr, nullptr }); + } + return *s_sys_variables; +} + +SysVariable& SysVariable::for_inode(InodeIdentifier id) +{ + auto index = to_sys_index(id); + if (index >= sys_variables().size()) + return sys_variables()[0]; + auto& variable = sys_variables()[index]; + ASSERT(variable.address); + return variable; +} + static ByteBuffer read_sys_bool(InodeIdentifier inode_id) { - auto inode_ptr = ProcFS::the().get_inode(inode_id); - if (!inode_ptr) - return {}; - auto& inode = static_cast<ProcFSInode&>(*inode_ptr); - ASSERT(inode.custom_data()); + auto& variable = SysVariable::for_inode(inode_id); + ASSERT(variable.type == SysVariable::Type::Boolean); + auto buffer = ByteBuffer::create_uninitialized(2); - auto& custom_data = *static_cast<const SysVariableData*>(inode.custom_data()); - ASSERT(custom_data.type == SysVariableData::Boolean); - ASSERT(custom_data.address); - auto* lockable_bool = reinterpret_cast<Lockable<bool>*>(custom_data.address); + auto* lockable_bool = reinterpret_cast<Lockable<bool>*>(variable.address); { LOCKER(lockable_bool->lock()); buffer[0] = lockable_bool->resource() ? '1' : '0'; @@ -674,57 +692,42 @@ static ByteBuffer read_sys_bool(InodeIdentifier inode_id) static ssize_t write_sys_bool(InodeIdentifier inode_id, const ByteBuffer& data) { - auto inode_ptr = ProcFS::the().get_inode(inode_id); - if (!inode_ptr) - return {}; - auto& inode = static_cast<ProcFSInode&>(*inode_ptr); - ASSERT(inode.custom_data()); + auto& variable = SysVariable::for_inode(inode_id); + ASSERT(variable.type == SysVariable::Type::Boolean); + if (data.is_empty() || !(data[0] == '0' || data[0] == '1')) return data.size(); - auto& custom_data = *static_cast<const SysVariableData*>(inode.custom_data()); - auto* lockable_bool = reinterpret_cast<Lockable<bool>*>(custom_data.address); + auto* lockable_bool = reinterpret_cast<Lockable<bool>*>(variable.address); { LOCKER(lockable_bool->lock()); lockable_bool->resource() = data[0] == '1'; } - if (custom_data.notify_callback) - custom_data.notify_callback(); + variable.notify(); return data.size(); } static ByteBuffer read_sys_string(InodeIdentifier inode_id) { - auto inode_ptr = ProcFS::the().get_inode(inode_id); - if (!inode_ptr) - return {}; - auto& inode = static_cast<ProcFSInode&>(*inode_ptr); - ASSERT(inode.custom_data()); - auto buffer = ByteBuffer::create_uninitialized(2); - auto& custom_data = *static_cast<const SysVariableData*>(inode.custom_data()); - ASSERT(custom_data.type == SysVariableData::String); - ASSERT(custom_data.address); - auto* lockable_string = reinterpret_cast<Lockable<String>*>(custom_data.address); + auto& variable = SysVariable::for_inode(inode_id); + ASSERT(variable.type == SysVariable::Type::String); + + auto* lockable_string = reinterpret_cast<Lockable<String>*>(variable.address); LOCKER(lockable_string->lock()); return lockable_string->resource().to_byte_buffer(); } static ssize_t write_sys_string(InodeIdentifier inode_id, const ByteBuffer& data) { - auto inode_ptr = ProcFS::the().get_inode(inode_id); - if (!inode_ptr) - return {}; - auto& inode = static_cast<ProcFSInode&>(*inode_ptr); - ASSERT(inode.custom_data()); - auto& custom_data = *static_cast<const SysVariableData*>(inode.custom_data()); - ASSERT(custom_data.address); + auto& variable = SysVariable::for_inode(inode_id); + ASSERT(variable.type == SysVariable::Type::String); + { - auto* lockable_string = reinterpret_cast<Lockable<String>*>(custom_data.address); + auto* lockable_string = reinterpret_cast<Lockable<String>*>(variable.address); LOCKER(lockable_string->lock()); lockable_string->resource() = String((const char*)data.pointer(), data.size()); } - if (custom_data.notify_callback) - custom_data.notify_callback(); + variable.notify(); return data.size(); } @@ -732,32 +735,39 @@ void ProcFS::add_sys_bool(String&& name, Lockable<bool>& var, Function<void()>&& { InterruptDisabler disabler; - int index = m_sys_entries.size(); - auto inode = adopt(*new ProcFSInode(*this, sys_var_to_identifier(fsid(), index).index())); - auto data = make<SysVariableData>(); - data->type = SysVariableData::Boolean; - data->notify_callback = move(notify_callback); - data->address = &var; - inode->set_custom_data(move(data)); - m_sys_entries.empend(strdup(name.characters()), 0, read_sys_bool, write_sys_bool, move(inode)); + SysVariable variable; + variable.name = move(name); + variable.type = SysVariable::Type::Boolean; + variable.notify_callback = move(notify_callback); + variable.address = &var; + + sys_variables().append(move(variable)); } void ProcFS::add_sys_string(String&& name, Lockable<String>& var, Function<void()>&& notify_callback) { InterruptDisabler disabler; - int index = m_sys_entries.size(); - auto inode = adopt(*new ProcFSInode(*this, sys_var_to_identifier(fsid(), index).index())); - auto data = make<SysVariableData>(); - data->type = SysVariableData::String; - data->notify_callback = move(notify_callback); - data->address = &var; - inode->set_custom_data(move(data)); - m_sys_entries.empend(strdup(name.characters()), 0, read_sys_string, write_sys_string, move(inode)); + SysVariable variable; + variable.name = move(name); + variable.type = SysVariable::Type::String; + variable.notify_callback = move(notify_callback); + variable.address = &var; + + sys_variables().append(move(variable)); } bool ProcFS::initialize() { + static Lockable<bool>* kmalloc_stack_helper; + + if (kmalloc_stack_helper == nullptr) { + kmalloc_stack_helper = new Lockable<bool>(); + kmalloc_stack_helper->resource() = g_dump_kmalloc_stacks; + ProcFS::add_sys_bool("kmalloc_stacks", *kmalloc_stack_helper, [] { + g_dump_kmalloc_stacks = kmalloc_stack_helper->resource(); + }); + } return true; } @@ -791,12 +801,6 @@ RefPtr<Inode> ProcFS::get_inode(InodeIdentifier inode_id) const if (inode_id == root_inode()) return m_root_inode; - if (to_proc_parent_directory(inode_id) == ProcParentDirectory::PDI_Root_sys) { - auto sys_index = to_sys_index(inode_id); - if (sys_index < m_sys_entries.size()) - return m_sys_entries[sys_index].inode; - } - LOCKER(m_inodes_lock); auto it = m_inodes.find(inode_id.index()); if (it == m_inodes.end()) { @@ -847,11 +851,6 @@ InodeMetadata ProcFSInode::metadata() const return metadata; } - if (proc_parent_directory == PDI_Root_sys) { - metadata.mode = 00100644; - return metadata; - } - switch (proc_file_type) { case FI_Root_self: case FI_PID_cwd: @@ -887,14 +886,30 @@ ssize_t ProcFSInode::read_bytes(off_t offset, ssize_t count, u8* buffer, FileDes Function<Optional<KBuffer>(InodeIdentifier)> callback_tmp; Function<Optional<KBuffer>(InodeIdentifier)>* read_callback { nullptr }; - if (directory_entry) { + if (directory_entry) read_callback = &directory_entry->read_callback; - } else { - if (to_proc_parent_directory(identifier()) == PDI_PID_fd) { + else + switch (to_proc_parent_directory(identifier())) { + case PDI_PID_fd: callback_tmp = procfs$pid_fd_entry; read_callback = &callback_tmp; + break; + case PDI_Root_sys: + switch (SysVariable::for_inode(identifier()).type) { + case SysVariable::Type::Invalid: + ASSERT_NOT_REACHED(); + case SysVariable::Type::Boolean: + callback_tmp = read_sys_bool; + break; + case SysVariable::Type::String: + callback_tmp = read_sys_string; + break; + } + read_callback = &callback_tmp; + break; + default: + ASSERT_NOT_REACHED(); } - } ASSERT(read_callback); @@ -953,9 +968,9 @@ bool ProcFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry&) break; case FI_Root_sys: - for (int i = 0; i < fs().m_sys_entries.size(); ++i) { - auto& entry = fs().m_sys_entries[i]; - callback({ entry.name, (int)strlen(entry.name), sys_var_to_identifier(fsid(), i), 0 }); + for (int i = 1; i < sys_variables().size(); ++i) { + auto& variable = sys_variables()[i]; + callback({ variable.name.characters(), variable.name.length(), sys_var_to_identifier(fsid(), i), 0 }); } break; @@ -1037,9 +1052,9 @@ InodeIdentifier ProcFSInode::lookup(StringView name) } if (proc_file_type == FI_Root_sys) { - for (int i = 0; i < fs().m_sys_entries.size(); ++i) { - auto& entry = fs().m_sys_entries[i]; - if (name == entry.name) + for (int i = 1; i < sys_variables().size(); ++i) { + auto& variable = sys_variables()[i]; + if (name == variable.name) return sys_var_to_identifier(fsid(), i); } return {}; @@ -1100,12 +1115,35 @@ void ProcFSInode::flush_metadata() ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, FileDescription*) { auto* directory_entry = fs().get_directory_entry(identifier()); - if (!directory_entry || !directory_entry->write_callback) - return -EPERM; + + Function<ssize_t(InodeIdentifier, const ByteBuffer&)> callback_tmp; + Function<ssize_t(InodeIdentifier, const ByteBuffer&)>* write_callback { nullptr }; + + if (directory_entry == nullptr) { + if (to_proc_parent_directory(identifier()) == PDI_Root_sys) { + switch (SysVariable::for_inode(identifier()).type) { + case SysVariable::Type::Invalid: + ASSERT_NOT_REACHED(); + case SysVariable::Type::Boolean: + callback_tmp = write_sys_bool; + break; + case SysVariable::Type::String: + callback_tmp = write_sys_string; + break; + } + write_callback = &callback_tmp; + } else + return -EPERM; + } else { + if (!directory_entry->write_callback) + return -EPERM; + write_callback = &directory_entry->write_callback; + } + ASSERT(is_persistent_inode(identifier())); // FIXME: Being able to write into ProcFS at a non-zero offset seems like something we should maybe support.. ASSERT(offset == 0); - bool success = directory_entry->write_callback(identifier(), ByteBuffer::wrap(buffer, size)); + bool success = (*write_callback)(identifier(), ByteBuffer::wrap(buffer, size)); ASSERT(success); return 0; } @@ -1123,10 +1161,6 @@ KResult ProcFSInode::remove_child(const StringView& name) return KResult(-EPERM); } -ProcFSInodeCustomData::~ProcFSInodeCustomData() -{ -} - size_t ProcFSInode::directory_entry_count() const { ASSERT(is_directory()); @@ -1145,7 +1179,6 @@ KResult ProcFSInode::chmod(mode_t) ProcFS::ProcFS() { - s_the = this; m_root_inode = adopt(*new ProcFSInode(*this, 1)); m_entries.resize(FI_MaxStaticFileIndex); m_entries[FI_Root_mm] = { "mm", FI_Root_mm, procfs$mm }; @@ -1176,23 +1209,12 @@ ProcFS::ProcFS() m_entries[FI_PID_exe] = { "exe", FI_PID_exe, procfs$pid_exe }; m_entries[FI_PID_cwd] = { "cwd", FI_PID_cwd, procfs$pid_cwd }; m_entries[FI_PID_fd] = { "fd", FI_PID_fd }; - - m_kmalloc_stack_helper.resource() = g_dump_kmalloc_stacks; - add_sys_bool("kmalloc_stacks", m_kmalloc_stack_helper, [this] { - g_dump_kmalloc_stacks = m_kmalloc_stack_helper.resource(); - }); } ProcFS::ProcFSDirectoryEntry* ProcFS::get_directory_entry(InodeIdentifier identifier) const { - if (to_proc_parent_directory(identifier) == PDI_Root_sys) { - auto sys_index = to_sys_index(identifier); - if (sys_index < m_sys_entries.size()) - return const_cast<ProcFSDirectoryEntry*>(&m_sys_entries[sys_index]); - return nullptr; - } auto proc_file_type = to_proc_file_type(identifier); - if (proc_file_type != FI_Invalid && proc_file_type < FI_MaxStaticFileIndex) + if (proc_file_type != FI_Invalid && proc_file_type != FI_Root_sys_variable && proc_file_type < FI_MaxStaticFileIndex) return const_cast<ProcFSDirectoryEntry*>(&m_entries[proc_file_type]); return nullptr; } diff --git a/Kernel/FileSystem/ProcFS.h b/Kernel/FileSystem/ProcFS.h index dc54cc65b5..1e10120c5d 100644 --- a/Kernel/FileSystem/ProcFS.h +++ b/Kernel/FileSystem/ProcFS.h @@ -14,8 +14,6 @@ class ProcFS final : public FS { friend class ProcFSInode; public: - static ProcFS& the(); - virtual ~ProcFS() override; static NonnullRefPtr<ProcFS> create(); @@ -28,9 +26,8 @@ public: virtual RefPtr<Inode> create_inode(InodeIdentifier parent_id, const String& name, mode_t, off_t size, dev_t, int& error) override; virtual RefPtr<Inode> create_directory(InodeIdentifier parent_id, const String& name, mode_t, int& error) override; - void add_sys_file(String&&, Function<ByteBuffer(ProcFSInode&)>&& read_callback, Function<ssize_t(ProcFSInode&, const ByteBuffer&)>&& write_callback); - void add_sys_bool(String&&, Lockable<bool>&, Function<void()>&& notify_callback = nullptr); - void add_sys_string(String&&, Lockable<String>&, Function<void()>&& notify_callback = nullptr); + static void add_sys_bool(String&&, Lockable<bool>&, Function<void()>&& notify_callback = nullptr); + static void add_sys_string(String&&, Lockable<String>&, Function<void()>&& notify_callback = nullptr); private: ProcFS(); @@ -57,16 +54,10 @@ private: ProcFSDirectoryEntry* get_directory_entry(InodeIdentifier) const; Vector<ProcFSDirectoryEntry> m_entries; - Vector<ProcFSDirectoryEntry> m_sys_entries; mutable Lock m_inodes_lock; mutable HashMap<unsigned, ProcFSInode*> m_inodes; RefPtr<ProcFSInode> m_root_inode; - Lockable<bool> m_kmalloc_stack_helper; -}; - -struct ProcFSInodeCustomData { - virtual ~ProcFSInodeCustomData(); }; class ProcFSInode final : public Inode { @@ -75,10 +66,6 @@ class ProcFSInode final : public Inode { public: virtual ~ProcFSInode() override; - void set_custom_data(OwnPtr<ProcFSInodeCustomData>&& custom_data) { m_custom_data = move(custom_data); } - ProcFSInodeCustomData* custom_data() { return m_custom_data.ptr(); } - const ProcFSInodeCustomData* custom_data() const { return m_custom_data.ptr(); } - private: // ^Inode virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override; @@ -96,6 +83,4 @@ private: ProcFS& fs() { return static_cast<ProcFS&>(Inode::fs()); } const ProcFS& fs() const { return static_cast<const ProcFS&>(Inode::fs()); } ProcFSInode(ProcFS&, unsigned index); - - OwnPtr<ProcFSInodeCustomData> m_custom_data; }; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 496e3fb5aa..b8bc868b7a 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -119,7 +119,9 @@ VFS* vfs; dbgprintf("Loaded ksyms\n"); // TODO: we should mount these from SystemServer - vfs->mount(ProcFS::the(), "/proc"); + auto procfs = ProcFS::create(); + procfs->initialize(); + vfs->mount(procfs, "/proc"); vfs->mount(DevPtsFS::the(), "/dev/pts"); auto tmpfs = TmpFS::create(); |