blob: 08daef3625b77a5039b7242134be072c9e9fbd7b [file] [log] [blame] [edit]
// 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