| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This file describes the structure used to access inodes. |
| // Currently, this structure is implemented on-disk as a table. |
| |
| #ifndef SRC_STORAGE_MINFS_ALLOCATOR_INODE_MANAGER_H_ |
| #define SRC_STORAGE_MINFS_ALLOCATOR_INODE_MANAGER_H_ |
| |
| #include <cstdio> |
| #include <memory> |
| |
| #include <fbl/macros.h> |
| |
| #include "src/storage/minfs/format.h" |
| |
| #ifdef __Fuchsia__ |
| #include <lib/fzl/resizeable-vmo-mapper.h> |
| |
| #include <block-client/cpp/block-device.h> |
| #endif |
| |
| #include "src/storage/minfs/allocator/allocator.h" |
| |
| namespace minfs { |
| |
| class InspectableInodeManager { |
| public: |
| virtual ~InspectableInodeManager() = default; |
| |
| // Gets immutable reference to the inode allocator. |
| virtual const Allocator* GetInodeAllocator() const = 0; |
| |
| // Loads the inode from storage. |
| virtual void Load(ino_t inode_num, Inode* out) const = 0; |
| |
| // Checks if the inode is allocated. |
| virtual bool CheckAllocated(uint32_t inode_num) const = 0; |
| }; |
| |
| // InodeManager is responsible for owning the persistent storage for inodes. |
| // |
| // It can be used to Load and Update inodes on storage. |
| // Additionally, it is responsible for allocating and freeing inodes. |
| class InodeManager : public InspectableInodeManager { |
| public: |
| InodeManager() = delete; |
| // Not copyable or movable |
| InodeManager(const InodeManager&) = delete; |
| InodeManager& operator=(const InodeManager&) = delete; |
| InodeManager(InodeManager&&) = delete; |
| InodeManager& operator=(InodeManager&&) = delete; |
| |
| ~InodeManager() override = default; |
| |
| #ifdef __Fuchsia__ |
| static zx_status_t Create(block_client::BlockDevice* device, SuperblockManager* sb, |
| fs::BufferedOperationsBuilder* builder, AllocatorMetadata metadata, |
| blk_t start_block, size_t inodes, std::unique_ptr<InodeManager>* out); |
| #else |
| static zx_status_t Create(Bcache* bc, SuperblockManager* sb, |
| fs::BufferedOperationsBuilder* builder, AllocatorMetadata metadata, |
| blk_t start_block, size_t inodes, std::unique_ptr<InodeManager>* out); |
| #endif |
| |
| // Reserve |inodes| inodes in the allocator. |
| static zx_status_t Reserve(PendingWork* transaction, size_t inodes, |
| AllocatorReservation* reservation) { |
| return reservation->Reserve(transaction, inodes); |
| } |
| |
| // Free an inode. |
| void Free(Transaction* transaction, size_t index) { |
| inode_allocator_->Free(&transaction->inode_reservation(), index); |
| } |
| |
| // Persist the inode to storage. |
| void Update(PendingWork* transaction, ino_t ino, const Inode* inode); |
| |
| // InspectableInodeManager interface: |
| const Allocator* GetInodeAllocator() const final; |
| |
| void Load(ino_t ino, Inode* out) const final; |
| |
| bool CheckAllocated(uint32_t inode_num) const final { |
| return inode_allocator_->CheckAllocated(inode_num); |
| } |
| |
| // Extend the number of inodes managed. |
| // |
| // It is the caller's responsibility to ensure that there is space |
| // on persistent storage for these inodes to be stored. |
| zx_status_t Grow(size_t inodes); |
| |
| Allocator& inode_allocator() { return *inode_allocator_; } |
| |
| private: |
| #ifdef __Fuchsia__ |
| explicit InodeManager(blk_t start_block, uint32_t block_size); |
| #else |
| InodeManager(Bcache* bc, blk_t start_block, uint32_t block_size); |
| #endif |
| |
| uint32_t BlockSize() const { |
| // Either intentionally or unintenttionally, we do not want to change block |
| // size to anything other than kMinfsBlockSize yet. This is because changing |
| // block size might lead to format change and also because anything other |
| // than 8k is not well tested. So assert when we find block size other |
| // than 8k. |
| ZX_ASSERT(block_size_ == kMinfsBlockSize); |
| return block_size_; |
| } |
| |
| blk_t start_block_; |
| |
| // Filesystem block size. |
| uint32_t block_size_ = {}; |
| std::unique_ptr<Allocator> inode_allocator_; |
| #ifdef __Fuchsia__ |
| fzl::ResizeableVmoMapper inode_table_; |
| #else |
| Bcache* bc_; |
| #endif |
| }; |
| |
| } // namespace minfs |
| |
| #endif // SRC_STORAGE_MINFS_ALLOCATOR_INODE_MANAGER_H_ |