Plan9FileSystem.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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 FileBackedFileSystem {
  14. friend class Plan9FSInode;
  15. public:
  16. virtual ~Plan9FS() override;
  17. static ErrorOr<NonnullRefPtr<FileSystem>> try_create(OpenFileDescription&);
  18. virtual ErrorOr<void> initialize() override;
  19. virtual bool supports_watchers() const override { return false; }
  20. virtual Inode& root_inode() 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(OpenFileDescription&);
  36. class Blocker;
  37. class Plan9FSBlockerSet final : public Thread::BlockerSet {
  38. public:
  39. Plan9FSBlockerSet(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 m_lock { LockRank::None };
  51. };
  52. struct ReceiveCompletion : public RefCounted<ReceiveCompletion> {
  53. mutable Spinlock lock { LockRank::None };
  54. bool completed { false };
  55. const u16 tag;
  56. OwnPtr<Message> message;
  57. ErrorOr<void> result;
  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. }
  69. virtual bool setup_blocker() override;
  70. virtual StringView state_string() const override { return "Waiting"sv; }
  71. virtual Type blocker_type() const override { return Type::Plan9FS; }
  72. virtual void will_unblock_immediately_without_blocking(UnblockImmediatelyReason) override;
  73. NonnullRefPtr<ReceiveCompletion> const& 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 StringView class_name() const override { return "Plan9FS"sv; }
  90. bool is_complete(ReceiveCompletion const&);
  91. ErrorOr<void> post_message(Message&, RefPtr<ReceiveCompletion>);
  92. ErrorOr<void> do_read(u8* buffer, size_t);
  93. ErrorOr<void> read_and_dispatch_one_message();
  94. ErrorOr<void> post_message_and_wait_for_a_reply(Message&);
  95. ErrorOr<void> post_message_and_explicitly_ignore_reply(Message&);
  96. ProtocolVersion parse_protocol_version(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. Mutex m_send_lock { "Plan9FS send"sv };
  106. Plan9FSBlockerSet m_completion_blocker;
  107. HashMap<u16, NonnullRefPtr<ReceiveCompletion>> m_completions;
  108. Spinlock m_thread_lock { LockRank::None };
  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 ErrorOr<void> flush_metadata() override;
  121. virtual ErrorOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override;
  122. virtual ErrorOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const& data, OpenFileDescription*) override;
  123. virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
  124. virtual ErrorOr<NonnullRefPtr<Inode>> lookup(StringView name) override;
  125. virtual ErrorOr<NonnullRefPtr<Inode>> create_child(StringView name, mode_t, dev_t, UserID, GroupID) override;
  126. virtual ErrorOr<void> add_child(Inode&, StringView name, mode_t) override;
  127. virtual ErrorOr<void> remove_child(StringView name) override;
  128. virtual ErrorOr<void> chmod(mode_t) override;
  129. virtual ErrorOr<void> chown(UserID, GroupID) override;
  130. virtual ErrorOr<void> truncate(u64) override;
  131. private:
  132. Plan9FSInode(Plan9FS&, u32 fid);
  133. static ErrorOr<NonnullRefPtr<Plan9FSInode>> try_create(Plan9FS&, u32 fid);
  134. enum class GetAttrMask : u64 {
  135. Mode = 0x1,
  136. NLink = 0x2,
  137. UID = 0x4,
  138. GID = 0x8,
  139. RDev = 0x10,
  140. ATime = 0x20,
  141. MTime = 0x40,
  142. CTime = 0x80,
  143. Ino = 0x100,
  144. Size = 0x200,
  145. Blocks = 0x400,
  146. BTime = 0x800,
  147. Gen = 0x1000,
  148. DataVersion = 0x2000,
  149. Basic = 0x7ff,
  150. All = 0x3fff
  151. };
  152. enum class SetAttrMask : u64 {
  153. Mode = 0x1,
  154. UID = 0x2,
  155. GID = 0x4,
  156. Size = 0x8,
  157. ATime = 0x10,
  158. MTime = 0x20,
  159. CTime = 0x40,
  160. ATimeSet = 0x80,
  161. MTimeSet = 0x100
  162. };
  163. // Mode in which the file is already open, using SerenityOS constants.
  164. int m_open_mode { 0 };
  165. ErrorOr<void> ensure_open_for_mode(int mode);
  166. Plan9FS& fs() { return reinterpret_cast<Plan9FS&>(Inode::fs()); }
  167. Plan9FS& fs() const
  168. {
  169. return const_cast<Plan9FS&>(reinterpret_cast<Plan9FS const&>(Inode::fs()));
  170. }
  171. };
  172. }