blob: 9a7f39bda1be69634667baa8f2129c9978803527 [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.
#include "src/storage/fvm/host/internal_snapshot_meta_format.h"
#include <inttypes.h>
#include <zircon/errors.h>
#include <limits>
#include <utility>
#include <safemath/checked_math.h>
#include "src/storage/fvm/host/format.h"
namespace {
template <class T>
uint32_t ToU32(T in) {
if (in > std::numeric_limits<uint32_t>::max()) {
fprintf(stderr, "%s:%d out of range %" PRIuMAX "\n", __FILE__, __LINE__,
safemath::checked_cast<uintmax_t>(in));
exit(-1);
}
return safemath::checked_cast<uint32_t>(in);
}
} // namespace
InternalSnapshotMetaFormat::InternalSnapshotMetaFormat(
size_t reserved_slices, size_t slice_size,
const std::vector<fvm::PartitionSnapshotState>& partitions,
const std::vector<fvm::SnapshotExtentType>& extents)
: Format(), reserved_slices_(reserved_slices), slice_size_(slice_size) {
meta_ = fvm::SnapshotMetadata::Synthesize(partitions.data(), partitions.size(), extents.data(),
extents.size())
.value();
zero_buf_ = std::unique_ptr<uint8_t[]>(new uint8_t[meta_.Get()->size()]);
}
InternalSnapshotMetaFormat::~InternalSnapshotMetaFormat() = default;
zx::status<ExtentInfo> InternalSnapshotMetaFormat::GetExtent(unsigned index) const {
if (index == 0) {
return zx::ok(ExtentInfo{
.vslice_start = 0,
.vslice_count = ToU32(reserved_slices_),
.block_offset = 0,
.block_count = 1,
.zero_fill = false,
});
}
return zx::error(ZX_ERR_OUT_OF_RANGE);
}
zx_status_t InternalSnapshotMetaFormat::GetSliceCount(uint32_t* slices_out) const {
*slices_out = reserved_slices_;
return ZX_OK;
}
zx_status_t InternalSnapshotMetaFormat::FillBlock(size_t block_offset) {
if (block_offset == 0) {
// We'll read directly from meta_ later.
reading_from_meta_ = true;
return ZX_OK;
}
reading_from_meta_ = false;
return ZX_OK;
}
zx_status_t InternalSnapshotMetaFormat::EmptyBlock() {
reading_from_meta_ = false;
return ZX_OK;
}
void* InternalSnapshotMetaFormat::Data() {
return reading_from_meta_ ? meta_.Get()->data() : zero_buf_.get();
}
const char* InternalSnapshotMetaFormat::Name() const { return "internal"; }
uint32_t InternalSnapshotMetaFormat::BlockSize() const { return meta_.Get()->size(); }
uint32_t InternalSnapshotMetaFormat::BlocksPerSlice() const {
return ToU32(slice_size_ / BlockSize());
}