DiskBackedFileSystem.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include "DiskBackedFileSystem.h"
  2. #include <AK/InlineLRUCache.h>
  3. #include <Kernel/Arch/i386/CPU.h>
  4. #include <Kernel/Process.h>
  5. //#define DBFS_DEBUG
  6. struct BlockIdentifier {
  7. unsigned fsid { 0 };
  8. unsigned index { 0 };
  9. bool operator==(const BlockIdentifier& other) const { return fsid == other.fsid && index == other.index; }
  10. };
  11. namespace AK {
  12. template<>
  13. struct Traits<BlockIdentifier> : public GenericTraits<BlockIdentifier> {
  14. static unsigned hash(const BlockIdentifier& block_id) { return pair_int_hash(block_id.fsid, block_id.index); }
  15. static void dump(const BlockIdentifier& block_id) { kprintf("[block %02u:%08u]", block_id.fsid, block_id.index); }
  16. };
  17. }
  18. class CachedBlock : public InlineLinkedListNode<CachedBlock> {
  19. public:
  20. CachedBlock(const BlockIdentifier& block_id, const ByteBuffer& buffer)
  21. : m_key(block_id)
  22. , m_buffer(buffer)
  23. {
  24. }
  25. BlockIdentifier m_key;
  26. CachedBlock* m_next { nullptr };
  27. CachedBlock* m_prev { nullptr };
  28. ByteBuffer m_buffer;
  29. };
  30. Lockable<InlineLRUCache<BlockIdentifier, CachedBlock>>& block_cache()
  31. {
  32. static Lockable<InlineLRUCache<BlockIdentifier, CachedBlock>>* s_cache;
  33. if (!s_cache)
  34. s_cache = new Lockable<InlineLRUCache<BlockIdentifier, CachedBlock>>;
  35. return *s_cache;
  36. }
  37. DiskBackedFS::DiskBackedFS(NonnullRefPtr<DiskDevice>&& device)
  38. : m_device(move(device))
  39. {
  40. }
  41. DiskBackedFS::~DiskBackedFS()
  42. {
  43. }
  44. bool DiskBackedFS::write_block(unsigned index, const ByteBuffer& data)
  45. {
  46. #ifdef DBFS_DEBUG
  47. kprintf("DiskBackedFileSystem::write_block %u, size=%u\n", index, data.size());
  48. #endif
  49. ASSERT(data.size() == block_size());
  50. {
  51. LOCKER(block_cache().lock());
  52. if (auto* cached_block = block_cache().resource().get({ fsid(), index }))
  53. cached_block->m_buffer = data;
  54. }
  55. LOCKER(m_lock);
  56. m_write_cache.set(index, data.isolated_copy());
  57. if (m_write_cache.size() >= 32)
  58. flush_writes();
  59. return true;
  60. }
  61. bool DiskBackedFS::write_blocks(unsigned index, unsigned count, const ByteBuffer& data)
  62. {
  63. #ifdef DBFS_DEBUG
  64. kprintf("DiskBackedFileSystem::write_blocks %u x%u\n", index, count);
  65. #endif
  66. for (unsigned i = 0; i < count; ++i)
  67. write_block(index + i, data.slice(i * block_size(), block_size()));
  68. return true;
  69. }
  70. ByteBuffer DiskBackedFS::read_block(unsigned index) const
  71. {
  72. #ifdef DBFS_DEBUG
  73. kprintf("DiskBackedFileSystem::read_block %u\n", index);
  74. #endif
  75. {
  76. LOCKER(m_lock);
  77. if (auto it = m_write_cache.find(index); it != m_write_cache.end())
  78. return it->value;
  79. }
  80. {
  81. LOCKER(block_cache().lock());
  82. if (auto* cached_block = block_cache().resource().get({ fsid(), index }))
  83. return cached_block->m_buffer;
  84. }
  85. auto buffer = ByteBuffer::create_uninitialized(block_size());
  86. //kprintf("created block buffer with size %u\n", block_size());
  87. DiskOffset base_offset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(block_size());
  88. auto* buffer_pointer = buffer.data();
  89. bool success = device().read(base_offset, block_size(), buffer_pointer);
  90. ASSERT(success);
  91. ASSERT(buffer.size() == block_size());
  92. {
  93. LOCKER(block_cache().lock());
  94. block_cache().resource().put({ fsid(), index }, CachedBlock({ fsid(), index }, buffer));
  95. }
  96. return buffer;
  97. }
  98. ByteBuffer DiskBackedFS::read_blocks(unsigned index, unsigned count) const
  99. {
  100. if (!count)
  101. return nullptr;
  102. if (count == 1)
  103. return read_block(index);
  104. auto blocks = ByteBuffer::create_uninitialized(count * block_size());
  105. u8* out = blocks.data();
  106. for (unsigned i = 0; i < count; ++i) {
  107. auto block = read_block(index + i);
  108. if (!block)
  109. return nullptr;
  110. memcpy(out, block.data(), block.size());
  111. out += block_size();
  112. }
  113. return blocks;
  114. }
  115. void DiskBackedFS::flush_writes()
  116. {
  117. LOCKER(m_lock);
  118. for (auto& it : m_write_cache) {
  119. DiskOffset base_offset = static_cast<DiskOffset>(it.key) * static_cast<DiskOffset>(block_size());
  120. device().write(base_offset, block_size(), it.value.data());
  121. }
  122. m_write_cache.clear();
  123. }