Inode.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. InlineLinkedList<Inode>& all_inodes()
  8. {
  9. static InlineLinkedList<Inode>* list;
  10. if (!list)
  11. list = new InlineLinkedList<Inode>;
  12. return *list;
  13. }
  14. void Inode::sync()
  15. {
  16. NonnullRefPtrVector<Inode, 32> inodes;
  17. {
  18. InterruptDisabler disabler;
  19. for (auto& inode : all_inodes()) {
  20. if (inode.is_metadata_dirty())
  21. inodes.append(inode);
  22. }
  23. }
  24. for (auto& inode : inodes) {
  25. ASSERT(inode.is_metadata_dirty());
  26. inode.flush_metadata();
  27. }
  28. }
  29. ByteBuffer Inode::read_entire(FileDescription* descriptor) const
  30. {
  31. size_t initial_size = metadata().size ? metadata().size : 4096;
  32. StringBuilder builder(initial_size);
  33. ssize_t nread;
  34. u8 buffer[4096];
  35. off_t offset = 0;
  36. for (;;) {
  37. nread = read_bytes(offset, sizeof(buffer), buffer, descriptor);
  38. ASSERT(nread <= (ssize_t)sizeof(buffer));
  39. if (nread <= 0)
  40. break;
  41. builder.append((const char*)buffer, nread);
  42. offset += nread;
  43. }
  44. if (nread < 0) {
  45. kprintf("Inode::read_entire: ERROR: %d\n", nread);
  46. return nullptr;
  47. }
  48. return builder.to_byte_buffer();
  49. }
  50. unsigned Inode::fsid() const
  51. {
  52. return m_fs.fsid();
  53. }
  54. Inode::Inode(FS& fs, unsigned index)
  55. : m_fs(fs)
  56. , m_index(index)
  57. {
  58. all_inodes().append(this);
  59. }
  60. Inode::~Inode()
  61. {
  62. all_inodes().remove(this);
  63. }
  64. void Inode::will_be_destroyed()
  65. {
  66. if (m_metadata_dirty)
  67. flush_metadata();
  68. }
  69. void Inode::inode_contents_changed(off_t offset, ssize_t size, const u8* data)
  70. {
  71. if (m_vmobject)
  72. m_vmobject->inode_contents_changed({}, offset, size, data);
  73. }
  74. void Inode::inode_size_changed(size_t old_size, size_t new_size)
  75. {
  76. if (m_vmobject)
  77. m_vmobject->inode_size_changed({}, old_size, new_size);
  78. }
  79. int Inode::set_atime(time_t)
  80. {
  81. return -ENOTIMPL;
  82. }
  83. int Inode::set_ctime(time_t)
  84. {
  85. return -ENOTIMPL;
  86. }
  87. int Inode::set_mtime(time_t)
  88. {
  89. return -ENOTIMPL;
  90. }
  91. int Inode::increment_link_count()
  92. {
  93. return -ENOTIMPL;
  94. }
  95. int Inode::decrement_link_count()
  96. {
  97. return -ENOTIMPL;
  98. }
  99. void Inode::set_vmobject(VMObject& vmobject)
  100. {
  101. m_vmobject = vmobject.make_weak_ptr();
  102. }
  103. bool Inode::bind_socket(LocalSocket& socket)
  104. {
  105. ASSERT(!m_socket);
  106. m_socket = socket;
  107. return true;
  108. }
  109. bool Inode::unbind_socket()
  110. {
  111. ASSERT(m_socket);
  112. m_socket = nullptr;
  113. return true;
  114. }
  115. void Inode::register_watcher(Badge<InodeWatcher>, InodeWatcher& watcher)
  116. {
  117. LOCKER(m_lock);
  118. ASSERT(!m_watchers.contains(&watcher));
  119. m_watchers.set(&watcher);
  120. }
  121. void Inode::unregister_watcher(Badge<InodeWatcher>, InodeWatcher& watcher)
  122. {
  123. LOCKER(m_lock);
  124. ASSERT(m_watchers.contains(&watcher));
  125. m_watchers.remove(&watcher);
  126. }
  127. void Inode::set_metadata_dirty(bool metadata_dirty)
  128. {
  129. if (m_metadata_dirty == metadata_dirty)
  130. return;
  131. m_metadata_dirty = metadata_dirty;
  132. if (m_metadata_dirty) {
  133. // FIXME: Maybe we should hook into modification events somewhere else, I'm not sure where.
  134. // We don't always end up on this particular code path, for instance when writing to an ext2fs file.
  135. LOCKER(m_lock);
  136. for (auto& watcher : m_watchers) {
  137. watcher->notify_inode_event({}, InodeWatcher::Event::Type::Modified);
  138. }
  139. }
  140. }