blob: aa7538da7504f090999d2fd708dc133812faf78b [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_FVM_SNAPSHOT_METADATA_H_
#define SRC_STORAGE_FVM_SNAPSHOT_METADATA_H_
#include <lib/zx/status.h>
#include <zircon/types.h>
#include <memory>
#include <optional>
#include "src/storage/fvm/metadata_buffer.h"
#include "src/storage/fvm/snapshot_metadata_format.h"
namespace fvm {
// SnapshotMetadata is an in-memory representation of the snapshot metadata for an FVM image.
//
// At construction, |SnapshotMetadata| objects are well-formed, since they validate the underlying
// metadata when first created by |SnapshotMetadata::Create| or |SnapshotMetadata::Synthesize|.
// Subsequent updates by clients can, of course, corrupt the metadata.
//
// This class owns the underlying buffer (see |MetadataBuffer)|.
//
// This class is not thread-safe.
class SnapshotMetadata {
public:
// Constructs a default, uninitialized instance.
SnapshotMetadata() = default;
SnapshotMetadata(const SnapshotMetadata&) = delete;
SnapshotMetadata& operator=(const SnapshotMetadata&) = delete;
SnapshotMetadata(SnapshotMetadata&&) noexcept;
SnapshotMetadata& operator=(SnapshotMetadata&&) noexcept;
// Returns the minimum number of bytes needed for a |MetadataBuffer| object to back FVM snapshot
// metadata described by |header|.
static size_t BytesNeeded(const SnapshotMetadataHeader& header);
// Attempts to parse the FVM metadata stored at |data_a| and |data_b|, picking the latest copy.
// The copy with the latest generation (that is also valid) will be retained; the other is
// discarded.
// Returns a |SnapshotMetadata| instance over the passed metadata on success, or a failure if
// neither was valid.
static zx::status<SnapshotMetadata> Create(std::unique_ptr<MetadataBuffer> data_a,
std::unique_ptr<MetadataBuffer> data_b);
// Creates an instance of |SnapshotMetadata|, initialized by copying the contents of |partitions|
// and |extents|.
// All of the passed metadata is copied into both the A and B slots. Any additional partitions
// and slices in the tables past |partitions| and |extents| are default-initialized.
static zx::status<SnapshotMetadata> Synthesize(const PartitionSnapshotState* partitions,
size_t num_partitions,
const SnapshotExtentType* extents,
size_t num_extents);
// Picks the valid copy stored in |a| and |b| that has the greatest generation number.
static std::optional<SnapshotMetadataCopy> PickValid(const void* a, const void* b,
size_t meta_size);
// Updates the hash stored in the metadata, based on its contents.
void UpdateHash();
// Returns the disk offset where the metadata should be persisted. This points to the
// offset of the *inactive* copy (see |inactive_header()|).
size_t GetInactiveHeaderOffset() const;
// Returns whether the Metadata represents an active A copy or B copy.
SnapshotMetadataCopy active_header() const { return active_header_; }
SnapshotMetadataCopy inactive_header() const { return OppositeHeader(active_header_); }
// Switches whether the Metadata represents an active A or B copy.
void SwitchActiveHeaders();
// Accesses the header managed by the Metadata instance.
SnapshotMetadataHeader& GetHeader() const;
// Accesses the partition state table. Note that |idx| is one-based.
// |idx| is the same as the index in the main partition table.
PartitionSnapshotState& GetPartitionStateEntry(size_t idx) const;
// Accesses the extent type table.
SnapshotExtentType& GetExtentTypeEntry(size_t idx) const;
// Gets a view of the raw metadata buffer.
const MetadataBuffer* Get() const;
private:
SnapshotMetadata(std::unique_ptr<MetadataBuffer> data, SnapshotMetadataCopy active_header);
static bool CheckHash(const void* metadata, size_t meta_size);
constexpr static SnapshotMetadataCopy OppositeHeader(SnapshotMetadataCopy type) {
switch (type) {
case SnapshotMetadataCopy::kPrimary:
return SnapshotMetadataCopy::kSecondary;
case SnapshotMetadataCopy::kSecondary:
return SnapshotMetadataCopy::kPrimary;
}
}
void MoveFrom(SnapshotMetadata&& o);
std::unique_ptr<MetadataBuffer> data_;
SnapshotMetadataCopy active_header_{SnapshotMetadataCopy::kPrimary};
};
} // namespace fvm
#endif // SRC_STORAGE_FVM_SNAPSHOT_METADATA_H_