| // Copyright 2019 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. |
| |
| #include "src/storage/minfs/inspector.h" |
| |
| #include <lib/syslog/cpp/macros.h> |
| #include <sys/stat.h> |
| |
| #include <block-client/cpp/block-device.h> |
| #include <disk_inspector/common_types.h> |
| #include <fbl/unique_fd.h> |
| #include <fs/journal/inspector_journal.h> |
| |
| #include "src/storage/minfs/bcache.h" |
| #include "src/storage/minfs/inspector_inode_table.h" |
| #include "src/storage/minfs/inspector_private.h" |
| #include "src/storage/minfs/inspector_superblock.h" |
| |
| namespace minfs { |
| |
| std::unique_ptr<disk_inspector::DiskObjectUint64> CreateUint64DiskObj(fbl::String fieldName, |
| const uint64_t* value) { |
| return std::make_unique<disk_inspector::DiskObjectUint64>(fieldName, value); |
| } |
| |
| std::unique_ptr<disk_inspector::DiskObjectUint32> CreateUint32DiskObj(fbl::String fieldName, |
| const uint32_t* value) { |
| return std::make_unique<disk_inspector::DiskObjectUint32>(fieldName, value); |
| } |
| |
| std::unique_ptr<disk_inspector::DiskObjectUint64Array> CreateUint64ArrayDiskObj( |
| fbl::String fieldName, const uint64_t* value, size_t size) { |
| return std::make_unique<disk_inspector::DiskObjectUint64Array>(fieldName, value, size); |
| } |
| |
| std::unique_ptr<disk_inspector::DiskObjectUint32Array> CreateUint32ArrayDiskObj( |
| fbl::String fieldName, const uint32_t* value, size_t size) { |
| return std::make_unique<disk_inspector::DiskObjectUint32Array>(fieldName, value, size); |
| } |
| |
| zx_status_t Inspector::GetRoot(std::unique_ptr<disk_inspector::DiskObject>* out) { |
| std::unique_ptr<minfs::Bcache> bc; |
| bool readonly_device = false; |
| zx_status_t status = CreateBcache(std::move(device_), &readonly_device, &bc); |
| if (status != ZX_OK) { |
| FX_LOGS(ERROR) << "cannot create block cache"; |
| return status; |
| } |
| |
| status = CreateRoot(std::move(bc), out); |
| if (status != ZX_OK) { |
| FX_LOGS(ERROR) << "cannot create root object"; |
| return status; |
| } |
| return ZX_OK; |
| } |
| |
| zx_status_t Inspector::CreateRoot(std::unique_ptr<Bcache> bc, |
| std::unique_ptr<disk_inspector::DiskObject>* out) { |
| MountOptions options = {}; |
| options.readonly_after_initialization = true; |
| options.repair_filesystem = false; |
| std::unique_ptr<Minfs> fs; |
| zx_status_t status = Minfs::Create(std::move(bc), options, &fs); |
| if (status != ZX_OK) { |
| FX_LOGS(ERROR) << "minfsInspector: Create Failed to Create Minfs: " << status; |
| return status; |
| } |
| *out = std::unique_ptr<disk_inspector::DiskObject>(new RootObject(std::move(fs))); |
| return ZX_OK; |
| } |
| |
| std::unique_ptr<disk_inspector::DiskObject> RootObject::GetSuperBlock() const { |
| return std::unique_ptr<disk_inspector::DiskObject>( |
| new SuperBlockObject(fs_->Info(), SuperblockType::kPrimary)); |
| } |
| |
| std::unique_ptr<disk_inspector::DiskObject> RootObject::GetInodeTable() const { |
| return std::unique_ptr<disk_inspector::DiskObject>(new InodeTableObject( |
| fs_->GetInodeManager(), fs_->Info().alloc_inode_count, fs_->Info().inode_count)); |
| } |
| |
| std::unique_ptr<disk_inspector::DiskObject> RootObject::GetJournal() const { |
| char data[kMinfsBlockSize]; |
| |
| const Superblock& superblock = fs_->Info(); |
| uint64_t start_block = JournalStartBlock(superblock); |
| uint64_t length = JournalBlocks(superblock); |
| if (fs_->ReadBlock(static_cast<blk_t>(start_block), data) < 0) { |
| FX_LOGS(ERROR) << "minfsInspector: could not read journal block"; |
| return nullptr; |
| } |
| fs::JournalInfo* info = reinterpret_cast<fs::JournalInfo*>(data); |
| return std::unique_ptr<disk_inspector::DiskObject>( |
| new fs::JournalObject(*info, start_block, length, fs_.get())); |
| } |
| |
| std::unique_ptr<disk_inspector::DiskObject> RootObject::GetBackupSuperBlock() const { |
| char data[kMinfsBlockSize]; |
| const Superblock& info = fs_->Info(); |
| |
| uint64_t location = |
| ((info.flags & kMinfsFlagFVM) == 0) ? kNonFvmSuperblockBackup : kFvmSuperblockBackup; |
| if (fs_->ReadBlock(static_cast<blk_t>(location), &data) < 0) { |
| FX_LOGS(ERROR) << "minfsInspector: could not read backup superblock"; |
| return nullptr; |
| } |
| auto backup_info = reinterpret_cast<Superblock&>(data); |
| return std::unique_ptr<disk_inspector::DiskObject>( |
| new SuperBlockObject(backup_info, SuperblockType::kBackup)); |
| } |
| |
| void RootObject::GetValue(const void** out_buffer, size_t* out_buffer_size) const { |
| ZX_DEBUG_ASSERT_MSG(false, "Invalid GetValue call for non primitive data type."); |
| } |
| |
| std::unique_ptr<disk_inspector::DiskObject> RootObject::GetElementAt(uint32_t index) const { |
| switch (index) { |
| case 0: { |
| // Super Block |
| return GetSuperBlock(); |
| } |
| case 1: { |
| // Inode Table |
| return GetInodeTable(); |
| } |
| case 2: { |
| // Journal |
| return GetJournal(); |
| } |
| case 3: { |
| // Backup Superblock |
| return GetBackupSuperBlock(); |
| } |
| }; |
| return nullptr; |
| } |
| |
| } // namespace minfs |