DiskBackedFileSystem.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #include "DiskBackedFileSystem.h"
  2. #include "i386.h"
  3. #include <AK/InlineLRUCache.h>
  4. //#define DBFS_DEBUG
  5. struct BlockIdentifier {
  6. unsigned fsid { 0 };
  7. unsigned index { 0 };
  8. bool operator==(const BlockIdentifier& other) const { return fsid == other.fsid && index == other.index; }
  9. };
  10. namespace AK {
  11. template<>
  12. struct Traits<BlockIdentifier> {
  13. static unsigned hash(const BlockIdentifier& block_id) { return pair_int_hash(block_id.fsid, block_id.index); }
  14. static void dump(const BlockIdentifier& block_id) { kprintf("[block %02u:%08u]", block_id.fsid, block_id.index); }
  15. };
  16. }
  17. class CachedBlock : public InlineLinkedListNode<CachedBlock> {
  18. public:
  19. CachedBlock(const BlockIdentifier& block_id, const ByteBuffer& buffer)
  20. : m_key(block_id)
  21. , m_buffer(buffer)
  22. {
  23. }
  24. BlockIdentifier m_key;
  25. CachedBlock* m_next { nullptr };
  26. CachedBlock* m_prev { nullptr };
  27. ByteBuffer m_buffer;
  28. };
  29. Lockable<InlineLRUCache<BlockIdentifier, CachedBlock>>& block_cache()
  30. {
  31. static Lockable<InlineLRUCache<BlockIdentifier, CachedBlock>>* s_cache;
  32. if (!s_cache)
  33. s_cache = new Lockable<InlineLRUCache<BlockIdentifier, CachedBlock>>;
  34. return *s_cache;
  35. }
  36. DiskBackedFS::DiskBackedFS(RetainPtr<DiskDevice>&& device)
  37. : m_device(move(device))
  38. {
  39. ASSERT(m_device);
  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. DiskOffset base_offset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(block_size());
  51. return device().write(base_offset, block_size(), data.pointer());
  52. }
  53. bool DiskBackedFS::write_blocks(unsigned index, unsigned count, const ByteBuffer& data)
  54. {
  55. #ifdef DBFS_DEBUG
  56. kprintf("DiskBackedFileSystem::write_blocks %u x%u\n", index, count);
  57. #endif
  58. DiskOffset base_offset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(block_size());
  59. return device().write(base_offset, count * block_size(), data.pointer());
  60. }
  61. ByteBuffer DiskBackedFS::read_block(unsigned index) const
  62. {
  63. #ifdef DBFS_DEBUG
  64. kprintf("DiskBackedFileSystem::read_block %u\n", index);
  65. #endif
  66. {
  67. LOCKER(block_cache().lock());
  68. if (auto* cached_block = block_cache().resource().get({ fsid(), index }))
  69. return cached_block->m_buffer;
  70. }
  71. auto buffer = ByteBuffer::create_uninitialized(block_size());
  72. //kprintf("created block buffer with size %u\n", block_size());
  73. DiskOffset base_offset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(block_size());
  74. auto* buffer_pointer = buffer.pointer();
  75. bool success = device().read(base_offset, block_size(), buffer_pointer);
  76. ASSERT(success);
  77. ASSERT(buffer.size() == block_size());
  78. {
  79. LOCKER(block_cache().lock());
  80. block_cache().resource().put({ fsid(), index }, CachedBlock({ fsid(), index }, buffer));
  81. }
  82. return buffer;
  83. }
  84. ByteBuffer DiskBackedFS::read_blocks(unsigned index, unsigned count) const
  85. {
  86. if (!count)
  87. return nullptr;
  88. if (count == 1)
  89. return read_block(index);
  90. auto blocks = ByteBuffer::create_uninitialized(count * block_size());
  91. byte* out = blocks.pointer();
  92. for (unsigned i = 0; i < count; ++i) {
  93. auto block = read_block(index + i);
  94. if (!block)
  95. return nullptr;
  96. memcpy(out, block.pointer(), block.size());
  97. out += block_size();
  98. }
  99. return blocks;
  100. }
  101. void DiskBackedFS::set_block_size(unsigned block_size)
  102. {
  103. if (block_size == m_block_size)
  104. return;
  105. m_block_size = block_size;
  106. }