Inode.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #include <AK/NonnullRefPtrVector.h>
  2. #include <AK/StringBuilder.h>
  3. #include <Kernel/FileSystem/Inode.h>
  4. #include <Kernel/FileSystem/InodeWatcher.h>
  5. #include <Kernel/Net/LocalSocket.h>
  6. #include <Kernel/VM/InodeVMObject.h>
  7. #include <Kernel/FileSystem/VirtualFileSystem.h>
  8. #include <Kernel/FileSystem/Custody.h>
  9. InlineLinkedList<Inode>& all_inodes()
  10. {
  11. static InlineLinkedList<Inode>* list;
  12. if (!list)
  13. list = new InlineLinkedList<Inode>;
  14. return *list;
  15. }
  16. void Inode::sync()
  17. {
  18. NonnullRefPtrVector<Inode, 32> inodes;
  19. {
  20. InterruptDisabler disabler;
  21. for (auto& inode : all_inodes()) {
  22. if (inode.is_metadata_dirty())
  23. inodes.append(inode);
  24. }
  25. }
  26. for (auto& inode : inodes) {
  27. ASSERT(inode.is_metadata_dirty());
  28. inode.flush_metadata();
  29. }
  30. }
  31. ByteBuffer Inode::read_entire(FileDescription* descriptor) const
  32. {
  33. size_t initial_size = metadata().size ? metadata().size : 4096;
  34. StringBuilder builder(initial_size);
  35. ssize_t nread;
  36. u8 buffer[4096];
  37. off_t offset = 0;
  38. for (;;) {
  39. nread = read_bytes(offset, sizeof(buffer), buffer, descriptor);
  40. ASSERT(nread <= (ssize_t)sizeof(buffer));
  41. if (nread <= 0)
  42. break;
  43. builder.append((const char*)buffer, nread);
  44. offset += nread;
  45. if (nread < (ssize_t)sizeof(buffer))
  46. break;
  47. }
  48. if (nread < 0) {
  49. kprintf("Inode::read_entire: ERROR: %d\n", nread);
  50. return nullptr;
  51. }
  52. return builder.to_byte_buffer();
  53. }
  54. KResultOr<NonnullRefPtr<Custody>> Inode::resolve_as_link(Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) const
  55. {
  56. // The default implementation simply treats the stored
  57. // contents as a path and resolves that. That is, it
  58. // behaves exactly how you would expect a symlink to work.
  59. auto contents = read_entire();
  60. if (!contents) {
  61. if (out_parent)
  62. *out_parent = nullptr;
  63. return KResult(-ENOENT);
  64. }
  65. auto path = StringView(contents.data(), contents.size());
  66. return VFS::the().resolve_path(path, base, out_parent, options, symlink_recursion_level);
  67. }
  68. unsigned Inode::fsid() const
  69. {
  70. return m_fs.fsid();
  71. }
  72. Inode::Inode(FS& fs, unsigned index)
  73. : m_fs(fs)
  74. , m_index(index)
  75. {
  76. all_inodes().append(this);
  77. }
  78. Inode::~Inode()
  79. {
  80. all_inodes().remove(this);
  81. }
  82. void Inode::will_be_destroyed()
  83. {
  84. if (m_metadata_dirty)
  85. flush_metadata();
  86. }
  87. void Inode::inode_contents_changed(off_t offset, ssize_t size, const u8* data)
  88. {
  89. if (m_vmobject)
  90. m_vmobject->inode_contents_changed({}, offset, size, data);
  91. }
  92. void Inode::inode_size_changed(size_t old_size, size_t new_size)
  93. {
  94. if (m_vmobject)
  95. m_vmobject->inode_size_changed({}, old_size, new_size);
  96. }
  97. int Inode::set_atime(time_t)
  98. {
  99. return -ENOTIMPL;
  100. }
  101. int Inode::set_ctime(time_t)
  102. {
  103. return -ENOTIMPL;
  104. }
  105. int Inode::set_mtime(time_t)
  106. {
  107. return -ENOTIMPL;
  108. }
  109. int Inode::increment_link_count()
  110. {
  111. return -ENOTIMPL;
  112. }
  113. int Inode::decrement_link_count()
  114. {
  115. return -ENOTIMPL;
  116. }
  117. void Inode::set_vmobject(VMObject& vmobject)
  118. {
  119. m_vmobject = vmobject.make_weak_ptr();
  120. }
  121. bool Inode::bind_socket(LocalSocket& socket)
  122. {
  123. ASSERT(!m_socket);
  124. m_socket = socket;
  125. return true;
  126. }
  127. bool Inode::unbind_socket()
  128. {
  129. ASSERT(m_socket);
  130. m_socket = nullptr;
  131. return true;
  132. }
  133. void Inode::register_watcher(Badge<InodeWatcher>, InodeWatcher& watcher)
  134. {
  135. LOCKER(m_lock);
  136. ASSERT(!m_watchers.contains(&watcher));
  137. m_watchers.set(&watcher);
  138. }
  139. void Inode::unregister_watcher(Badge<InodeWatcher>, InodeWatcher& watcher)
  140. {
  141. LOCKER(m_lock);
  142. ASSERT(m_watchers.contains(&watcher));
  143. m_watchers.remove(&watcher);
  144. }
  145. void Inode::set_metadata_dirty(bool metadata_dirty)
  146. {
  147. if (m_metadata_dirty == metadata_dirty)
  148. return;
  149. m_metadata_dirty = metadata_dirty;
  150. if (m_metadata_dirty) {
  151. // FIXME: Maybe we should hook into modification events somewhere else, I'm not sure where.
  152. // We don't always end up on this particular code path, for instance when writing to an ext2fs file.
  153. LOCKER(m_lock);
  154. for (auto& watcher : m_watchers) {
  155. watcher->notify_inode_event({}, InodeWatcher::Event::Type::Modified);
  156. }
  157. }
  158. }