Serenity Operating System
at master 156 lines 6.0 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#pragma once 9 10#include <AK/Error.h> 11#include <AK/Function.h> 12#include <AK/HashTable.h> 13#include <AK/IntrusiveList.h> 14#include <Kernel/FileSystem/FIFO.h> 15#include <Kernel/FileSystem/FileSystem.h> 16#include <Kernel/FileSystem/InodeIdentifier.h> 17#include <Kernel/FileSystem/InodeMetadata.h> 18#include <Kernel/Forward.h> 19#include <Kernel/Library/ListedRefCounted.h> 20#include <Kernel/Library/LockWeakPtr.h> 21#include <Kernel/Locking/Mutex.h> 22#include <Kernel/Memory/SharedInodeVMObject.h> 23 24namespace Kernel { 25 26enum class ShouldBlock { 27 No = 0, 28 Yes = 1 29}; 30 31class Inode : public ListedRefCounted<Inode, LockType::Spinlock> 32 , public LockWeakable<Inode> { 33 friend class VirtualFileSystem; 34 friend class FileSystem; 35 friend class InodeFile; 36 37public: 38 virtual ~Inode(); 39 40 virtual void remove_from_secondary_lists() { } 41 42 FileSystem& fs() { return m_file_system; } 43 FileSystem const& fs() const { return m_file_system; } 44 FileSystemID fsid() const { return m_file_system.fsid(); } 45 InodeIndex index() const { return m_index; } 46 47 size_t size() const { return metadata().size; } 48 bool is_symlink() const { return metadata().is_symlink(); } 49 bool is_directory() const { return metadata().is_directory(); } 50 bool is_character_device() const { return metadata().is_character_device(); } 51 mode_t mode() const { return metadata().mode; } 52 53 InodeIdentifier identifier() const { return { fsid(), index() }; } 54 virtual InodeMetadata metadata() const = 0; 55 56 ErrorOr<NonnullOwnPtr<KBuffer>> read_entire(OpenFileDescription* = nullptr) const; 57 58 ErrorOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*); 59 ErrorOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const; 60 61 virtual ErrorOr<void> attach(OpenFileDescription&) { return {}; } 62 virtual void detach(OpenFileDescription&) { } 63 virtual void did_seek(OpenFileDescription&, off_t) { } 64 virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const = 0; 65 virtual ErrorOr<NonnullRefPtr<Inode>> lookup(StringView name) = 0; 66 virtual ErrorOr<NonnullRefPtr<Inode>> create_child(StringView name, mode_t, dev_t, UserID, GroupID) = 0; 67 virtual ErrorOr<void> add_child(Inode&, StringView name, mode_t) = 0; 68 virtual ErrorOr<void> remove_child(StringView name) = 0; 69 /// Replace child atomically, incrementing the link count of the replacement 70 /// inode and decrementing the older inode's. 71 virtual ErrorOr<void> replace_child(StringView name, Inode&) = 0; 72 virtual ErrorOr<void> chmod(mode_t) = 0; 73 virtual ErrorOr<void> chown(UserID, GroupID) = 0; 74 virtual ErrorOr<void> truncate(u64) { return {}; } 75 76 ErrorOr<NonnullRefPtr<Custody>> resolve_as_link(Credentials const&, Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) const; 77 78 virtual ErrorOr<int> get_block_address(int) { return ENOTSUP; } 79 80 LockRefPtr<LocalSocket> bound_socket() const; 81 bool bind_socket(LocalSocket&); 82 bool unbind_socket(); 83 84 bool is_metadata_dirty() const { return m_metadata_dirty; } 85 86 virtual ErrorOr<void> update_timestamps(Optional<Time> atime, Optional<Time> ctime, Optional<Time> mtime); 87 virtual ErrorOr<void> increment_link_count(); 88 virtual ErrorOr<void> decrement_link_count(); 89 90 virtual ErrorOr<void> flush_metadata() = 0; 91 92 void will_be_destroyed(); 93 94 ErrorOr<void> set_shared_vmobject(Memory::SharedInodeVMObject&); 95 LockRefPtr<Memory::SharedInodeVMObject> shared_vmobject() const; 96 97 static void sync_all(); 98 void sync(); 99 100 bool has_watchers() const; 101 102 ErrorOr<void> register_watcher(Badge<InodeWatcher>, InodeWatcher&); 103 void unregister_watcher(Badge<InodeWatcher>, InodeWatcher&); 104 105 ErrorOr<NonnullRefPtr<FIFO>> fifo(); 106 107 bool can_apply_flock(flock const&, Optional<OpenFileDescription const&> = {}) const; 108 ErrorOr<void> apply_flock(Process const&, OpenFileDescription const&, Userspace<flock const*>, ShouldBlock); 109 ErrorOr<void> get_flock(OpenFileDescription const&, Userspace<flock*>) const; 110 void remove_flocks_for_description(OpenFileDescription const&); 111 Thread::FlockBlockerSet& flock_blocker_set() { return m_flock_blocker_set; }; 112 113protected: 114 Inode(FileSystem&, InodeIndex); 115 void set_metadata_dirty(bool); 116 ErrorOr<void> prepare_to_write_data(); 117 118 void did_add_child(InodeIdentifier child_id, StringView); 119 void did_remove_child(InodeIdentifier child_id, StringView); 120 void did_modify_contents(); 121 void did_delete_self(); 122 123 mutable Mutex m_inode_lock { "Inode"sv }; 124 125 virtual ErrorOr<size_t> write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*) = 0; 126 virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const = 0; 127 128private: 129 ErrorOr<bool> try_apply_flock(Process const&, OpenFileDescription const&, flock const&); 130 131 FileSystem& m_file_system; 132 InodeIndex m_index { 0 }; 133 LockWeakPtr<Memory::SharedInodeVMObject> m_shared_vmobject; 134 LockWeakPtr<LocalSocket> m_bound_socket; 135 SpinlockProtected<HashTable<InodeWatcher*>, LockRank::None> m_watchers {}; 136 bool m_metadata_dirty { false }; 137 RefPtr<FIFO> m_fifo; 138 IntrusiveListNode<Inode> m_inode_list_node; 139 140 struct Flock { 141 off_t start; 142 off_t len; 143 OpenFileDescription const* owner; 144 pid_t pid; 145 short type; 146 }; 147 148 Thread::FlockBlockerSet m_flock_blocker_set; 149 SpinlockProtected<Vector<Flock>, LockRank::None> m_flocks {}; 150 151public: 152 using AllInstancesList = IntrusiveList<&Inode::m_inode_list_node>; 153 static SpinlockProtected<Inode::AllInstancesList, LockRank::None>& all_instances(); 154}; 155 156}