blob: 1c56bb8e9db791595e78021d0b3979d6b62e63b8 [file] [log] [blame]
// 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_BLOBFS_BLOBFS_INSPECTOR_H_
#define SRC_STORAGE_BLOBFS_BLOBFS_INSPECTOR_H_
#include <lib/zx/result.h>
#include <string>
#include <vector>
#include <disk_inspector/buffer_factory.h>
#include <disk_inspector/common_types.h>
#include <disk_inspector/loader.h>
#include "src/storage/blobfs/format.h"
#include "src/storage/lib/vfs/cpp/journal/format.h"
#include "src/storage/lib/vfs/cpp/transaction/transaction_handler.h"
namespace blobfs {
// Bare-bone blobfs inspector that loads metadata from the backing block device and provides
// functions to return parsed structs.
class BlobfsInspector {
public:
// Creates a BlobfsInspector from a block device. Tries to load the superblock from disk upon
// creation by calling ReloadSuperblock().
static zx::result<std::unique_ptr<BlobfsInspector>> Create(
std::unique_ptr<fs::TransactionHandler> handler,
std::unique_ptr<disk_inspector::BufferFactory> factory);
// For functions which allow passing in a block buffer to either read/write data, users need to
// make sure that the buffer is compatible with the inspector's |handler_|. We expose the buffer
// factory here for users to grab buffers that work with the handler if they cannot create
// compatible buffers themselves.
const disk_inspector::BufferFactory* GetBufferFactory() const { return buffer_factory_.get(); }
// 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 BlobfsInspector 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 fpromise::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.
zx::result<std::vector<Inode>> InspectInodeRange(uint64_t start_index, uint64_t end_index);
// Loads the first journal block
zx::result<fs::JournalInfo> 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>
zx::result<T> InspectJournalEntryAs(uint64_t index);
// Loads the data bitmap blocks where the allocation bits for data blocks from |start_index|
// inclusive to |end_index| exclusive are located from disk and returns the indices for which the
// corresponding bits are allocated.
zx::result<std::vector<uint64_t>> InspectDataBlockAllocatedInRange(uint64_t start_index,
uint64_t end_index);
// Writes the |superblock| argument to disk and sets |superblock_| to |superblock| if the write
// succeeds.
zx::result<> WriteSuperblock(Superblock superblock);
// Writes the vector of |inodes| to disk as the range of inodes starting at |start_index| based on
// |superblock_| specified location. If users wish to write ExtentContainers, we expect them to
// treat the containers as Inodes and use this function to write them.
zx::result<> WriteInodes(std::vector<Inode> inodes, uint64_t start_index);
// Writes the |journal_info| as the journal superblock based on |superblock_| specified location.
zx::result<> WriteJournalSuperblock(fs::JournalInfo journal_info);
// Treats the entire |buffer| as journal entry blocks and writes the entire buffer to disk
// starting at the |start_index| journal entry block.
zx::result<> WriteJournalEntryBlocks(storage::BlockBuffer* buffer, uint64_t start_index);
// Sets the block allocation bitmap bits starting from |start_index| inclusive to |end_index|
// exclusive to |value| based on |superblock_| specified location.
zx::result<> WriteDataBlockAllocationBits(bool value, uint64_t start_index, uint64_t end_index);
// Writes the entire |buffer| to the data segment of disk starting at |start_index| data block
// based on |superblock_| specified location.
zx::result<> WriteDataBlocks(storage::BlockBuffer* buffer, uint64_t start_index);
private:
explicit BlobfsInspector(std::unique_ptr<fs::TransactionHandler> handler,
std::unique_ptr<disk_inspector::BufferFactory> buffer_factory);
zx_status_t LoadNodeElement(storage::BlockBuffer* buffer, uint64_t index);
zx_status_t LoadJournalEntry(storage::BlockBuffer* buffer, uint64_t index);
std::unique_ptr<fs::TransactionHandler> handler_;
std::unique_ptr<disk_inspector::BufferFactory> buffer_factory_;
disk_inspector::Loader loader_;
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 blobfs
#endif // SRC_STORAGE_BLOBFS_BLOBFS_INSPECTOR_H_