Plan9FileSystem.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /*
  2. * Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Atomic.h>
  8. #include <Kernel/FileSystem/FileBackedFileSystem.h>
  9. #include <Kernel/FileSystem/Inode.h>
  10. #include <Kernel/KBufferBuilder.h>
  11. namespace Kernel {
  12. class Plan9FSInode;
  13. class Plan9FS final : public FileBackedFS {
  14. friend class Plan9FSInode;
  15. public:
  16. virtual ~Plan9FS() override;
  17. static NonnullRefPtr<Plan9FS> create(FileDescription&);
  18. virtual bool initialize() override;
  19. virtual bool supports_watchers() const override { return false; }
  20. virtual NonnullRefPtr<Inode> root_inode() const override;
  21. u16 allocate_tag() { return m_next_tag++; }
  22. u32 allocate_fid() { return m_next_fid++; }
  23. enum class ProtocolVersion {
  24. v9P2000,
  25. v9P2000u,
  26. v9P2000L
  27. };
  28. struct qid {
  29. u8 type;
  30. u32 version;
  31. u64 path;
  32. };
  33. class Message;
  34. private:
  35. Plan9FS(FileDescription&);
  36. class Blocker;
  37. class Plan9FSBlockCondition : public Thread::BlockCondition {
  38. public:
  39. Plan9FSBlockCondition(Plan9FS& fs)
  40. : m_fs(fs)
  41. {
  42. }
  43. void unblock_completed(u16);
  44. void unblock_all();
  45. void try_unblock(Blocker&);
  46. protected:
  47. virtual bool should_add_blocker(Thread::Blocker&, void*) override;
  48. private:
  49. Plan9FS& m_fs;
  50. mutable SpinLock<u8> m_lock;
  51. };
  52. struct ReceiveCompletion : public RefCounted<ReceiveCompletion> {
  53. mutable SpinLock<u8> lock;
  54. bool completed { false };
  55. const u16 tag;
  56. OwnPtr<Message> message;
  57. KResult result { KSuccess };
  58. ReceiveCompletion(u16 tag);
  59. ~ReceiveCompletion();
  60. };
  61. class Blocker final : public Thread::Blocker {
  62. public:
  63. Blocker(Plan9FS& fs, Message& message, NonnullRefPtr<ReceiveCompletion> completion)
  64. : m_fs(fs)
  65. , m_message(message)
  66. , m_completion(move(completion))
  67. {
  68. set_block_condition(fs.m_completion_blocker);
  69. }
  70. virtual const char* state_string() const override { return "Waiting"; }
  71. virtual Type blocker_type() const override { return Type::Plan9FS; }
  72. virtual void not_blocking(bool) override;
  73. const NonnullRefPtr<ReceiveCompletion>& completion() const { return m_completion; }
  74. u16 tag() const { return m_completion->tag; }
  75. bool is_completed() const;
  76. bool unblock()
  77. {
  78. unblock_from_blocker();
  79. return true;
  80. }
  81. bool unblock(u16 tag);
  82. private:
  83. Plan9FS& m_fs;
  84. Message& m_message;
  85. NonnullRefPtr<ReceiveCompletion> m_completion;
  86. bool m_did_unblock { false };
  87. };
  88. friend class Blocker;
  89. virtual const char* class_name() const override { return "Plan9FS"; }
  90. bool is_complete(const ReceiveCompletion&);
  91. KResult post_message(Message&, RefPtr<ReceiveCompletion>);
  92. KResult do_read(u8* buffer, size_t);
  93. KResult read_and_dispatch_one_message();
  94. KResult post_message_and_wait_for_a_reply(Message&);
  95. KResult post_message_and_explicitly_ignore_reply(Message&);
  96. ProtocolVersion parse_protocol_version(const StringView&) const;
  97. size_t adjust_buffer_size(size_t size) const;
  98. void thread_main();
  99. void ensure_thread();
  100. RefPtr<Plan9FSInode> m_root_inode;
  101. Atomic<u16> m_next_tag { (u16)-1 };
  102. Atomic<u32> m_next_fid { 1 };
  103. ProtocolVersion m_remote_protocol_version { ProtocolVersion::v9P2000 };
  104. size_t m_max_message_size { 4 * KiB };
  105. Lock m_send_lock { "Plan9FS send" };
  106. Plan9FSBlockCondition m_completion_blocker;
  107. HashMap<u16, NonnullRefPtr<ReceiveCompletion>> m_completions;
  108. SpinLock<u8> m_thread_lock;
  109. RefPtr<Thread> m_thread;
  110. Atomic<bool> m_thread_running { false };
  111. Atomic<bool, AK::MemoryOrder::memory_order_relaxed> m_thread_shutdown { false };
  112. };
  113. class Plan9FSInode final : public Inode {
  114. friend class Plan9FS;
  115. public:
  116. virtual ~Plan9FSInode() override;
  117. u32 fid() const { return index().value(); }
  118. // ^Inode
  119. virtual InodeMetadata metadata() const override;
  120. virtual void flush_metadata() override;
  121. virtual KResultOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer& buffer, FileDescription*) const override;
  122. virtual KResultOr<size_t> write_bytes(off_t, size_t, const UserOrKernelBuffer& data, FileDescription*) override;
  123. virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
  124. virtual RefPtr<Inode> lookup(StringView name) override;
  125. virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override;
  126. virtual KResult add_child(Inode&, const StringView& name, mode_t) override;
  127. virtual KResult remove_child(const StringView& name) override;
  128. virtual KResultOr<size_t> directory_entry_count() const override;
  129. virtual KResult chmod(mode_t) override;
  130. virtual KResult chown(uid_t, gid_t) override;
  131. virtual KResult truncate(u64) override;
  132. private:
  133. Plan9FSInode(Plan9FS&, u32 fid);
  134. static NonnullRefPtr<Plan9FSInode> create(Plan9FS&, u32 fid);
  135. enum class GetAttrMask : u64 {
  136. Mode = 0x1,
  137. NLink = 0x2,
  138. UID = 0x4,
  139. GID = 0x8,
  140. RDev = 0x10,
  141. ATime = 0x20,
  142. MTime = 0x40,
  143. CTime = 0x80,
  144. Ino = 0x100,
  145. Size = 0x200,
  146. Blocks = 0x400,
  147. BTime = 0x800,
  148. Gen = 0x1000,
  149. DataVersion = 0x2000,
  150. Basic = 0x7ff,
  151. All = 0x3fff
  152. };
  153. enum class SetAttrMask : u64 {
  154. Mode = 0x1,
  155. UID = 0x2,
  156. GID = 0x4,
  157. Size = 0x8,
  158. ATime = 0x10,
  159. MTime = 0x20,
  160. CTime = 0x40,
  161. ATimeSet = 0x80,
  162. MTimeSet = 0x100
  163. };
  164. // Mode in which the file is already open, using SerenityOS constants.
  165. int m_open_mode { 0 };
  166. KResult ensure_open_for_mode(int mode);
  167. Plan9FS& fs() { return reinterpret_cast<Plan9FS&>(Inode::fs()); }
  168. Plan9FS& fs() const
  169. {
  170. return const_cast<Plan9FS&>(reinterpret_cast<const Plan9FS&>(Inode::fs()));
  171. }
  172. };
  173. }