| // Copyright 2020 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. |
| |
| #ifndef SRC_STORAGE_MINFS_MINFS_INSPECTOR_H_ |
| #define SRC_STORAGE_MINFS_MINFS_INSPECTOR_H_ |
| |
| #include <string> |
| #include <vector> |
| |
| #include <block-client/cpp/block-device.h> |
| #include <disk_inspector/buffer_factory.h> |
| #include <disk_inspector/common_types.h> |
| #include <disk_inspector/inspector_transaction_handler.h> |
| #include <fs/journal/format.h> |
| |
| #include "src/storage/minfs/format.h" |
| |
| namespace minfs { |
| |
| // Bare-bone minfs inspector that loads metadata from the backing block |
| // device and provides functions to return parsed structs. |
| // TODO(fxbug.dev/47359): Since this can run on corrupt data, more thought needs |
| // to be put on the potential edge cases that can happen during corruption. |
| // Care needs to be put into what dependencies are used when exposing new |
| // information from this class. |
| class MinfsInspector { |
| public: |
| // Creates a MinfsInspector from a block device. Tries to load the |
| // superblock from disk upon creation by calling ReloadSuperblock(). |
| static fit::result<std::unique_ptr<MinfsInspector>, zx_status_t> Create( |
| std::unique_ptr<fs::TransactionHandler> handler, |
| std::unique_ptr<disk_inspector::BufferFactory> factory); |
| |
| // This function is used to initialize minfs metadata buffers and to load the relavent data. |
| zx_status_t Initialize(); |
| |
| // Initializes the |superblock_| buffer and tries to load the superblock |
| // from disk into the buffer. The MinfsInspector should be considered invalid |
| // and should not be used if this function fails as either VmoBuffers cannot |
| // be created or we cannot read even the first block from the underlying |
| // block device. |
| zx_status_t ReloadSuperblock(); |
| |
| // Initializes the |inode_bitmap_|, |inode_table_|, and |journal_| buffers |
| // based on |superblock_| and tries to load the associated structs from disk |
| // into these buffers. Note: we do not consider the failure of initializing |
| // and loading of any of these buffers to be errors to crash the program as |
| // the class should still work to a reasonable degree in the case of debugging |
| // a superblock with corruptions. For cases of failure, these bufffers have |
| // undefined size and data inside. It is up to users to make sure that they |
| // make valid calls using other functions in this class. |
| void ReloadMetadataFromSuperblock(); |
| |
| // Returns a copy of |superblock_|. |
| Superblock InspectSuperblock(); |
| |
| // Returns the number of inodes from |superblock_|. |
| uint64_t GetInodeCount(); |
| |
| // Returns the number of journal entires calculated from |superblock_|. |
| uint64_t GetJournalEntryCount(); |
| |
| // The following functions need to load data from disk, leading to the |
| // possibility of failed loads. Since they need to return values, we have |
| // fit::results for all of the return types. In addition, they all depend |
| // on the loaded |superblock_| value to get where to start indexing. |
| |
| // Loads the inode table blocks for which the inodes from |start_index| inclusive |
| // to |end_index| exclusive from disk and returns the Inodes in the range as |
| // a vector. |
| fit::result<std::vector<Inode>, zx_status_t> InspectInodeRange(uint64_t start_index, |
| uint64_t end_index); |
| |
| // Loads the inode bitmap blocks for which the inode allocation bits for inodes |
| // from |start_index| inclusive to |end_index| exclusive from disk and returns |
| // the inode indices for which the corresponding bits are allocated. |
| fit::result<std::vector<uint64_t>, zx_status_t> InspectInodeAllocatedInRange(uint64_t start_index, |
| uint64_t end_index); |
| |
| // Loads the first journal block |
| fit::result<fs::JournalInfo, zx_status_t> InspectJournalSuperblock(); |
| |
| // Loads the |index| element journal entry block and returns it as a struct |
| // of type T. Only supports casting to fs::JournalPrefix, fs::JournalHeaderBlock, |
| // and fs::JournalCommitBlock. |
| template <typename T> |
| fit::result<T, zx_status_t> InspectJournalEntryAs(uint64_t index); |
| |
| // Loads and returns the backup superblock. |
| fit::result<Superblock, zx_status_t> InspectBackupSuperblock(); |
| |
| // Writes the |superblock| argument to disk and sets |superblock_| to |superblock| |
| // if the write succeeds. |
| fit::result<void, zx_status_t> WriteSuperblock(Superblock superblock); |
| |
| private: |
| explicit MinfsInspector(std::unique_ptr<fs::TransactionHandler> handler, |
| std::unique_ptr<disk_inspector::BufferFactory> buffer_factory); |
| |
| zx_status_t LoadJournalEntry(storage::BlockBuffer* buffer, uint64_t index); |
| |
| std::unique_ptr<fs::TransactionHandler> handler_; |
| std::unique_ptr<disk_inspector::BufferFactory> buffer_factory_; |
| Superblock superblock_; |
| // Scratch buffer initialized to be a single block in the Create method. |
| // Functions that use this buffer should try to treat it as an initialized |
| // buffer only valid for the duration of the function without any presaved |
| // state or ability for the function to save state. |
| std::unique_ptr<storage::BlockBuffer> buffer_; |
| }; |
| |
| } // namespace minfs |
| |
| #endif // SRC_STORAGE_MINFS_MINFS_INSPECTOR_H_ |