1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <fbl/unique_fd.h>
8 #include <fvm/fvm-sparse.h>
9 
10 // Wrapper around FVM metadata which attempts to read existing metadata from disk, allows
11 // new partitions and slices to be allocated, and writes updated metadata back to disk.
12 class FvmInfo {
13 public:
FvmInfo()14     FvmInfo() : valid_(false), dirty_(false), metadata_size_(0), vpart_hint_(1), pslice_hint_(1) {}
15 
16     // Resets the metadata to default values.
17     zx_status_t Reset(size_t disk_size, size_t slice_size);
18 
19     // Loads and validates metadata from disk. If invalid metadata is found a success status is
20     // returned, but valid_ is marked false.
21     zx_status_t Load(const fbl::unique_fd& fd, uint64_t disk_offset, uint64_t disk_size);
22 
23     // Validates the loaded metadata.
24     zx_status_t Validate() const;
25 
26     // Grows in-memory metadata representation to the specified size.
27     zx_status_t Grow(size_t metadata_size);
28 
29     // Grows in-memory metadata representation to account for |slice_count| additional slices.
30     zx_status_t GrowForSlices(size_t slice_count);
31 
32     // Writes metadata to the partition described by |fd| of size |disk_size|, starting at offset
33     // |disk_offset|.
34     zx_status_t Write(const fbl::unique_fd& fd, size_t disk_offset, size_t disk_size);
35 
36     // Allocates new partition (in memory) with a single slice.
37     zx_status_t AllocatePartition(const fvm::partition_descriptor_t* partition, uint8_t* guid,
38                                   uint32_t* vpart_index);
39 
40     // Allocates new slice for given partition (in memory).
41     zx_status_t AllocateSlice(uint32_t vpart, uint32_t vslice, uint32_t* pslice);
42 
43     // Helpers to grab reference to partition/slice from metadata
44     zx_status_t GetPartition(size_t index, fvm::vpart_entry_t** out) const;
45     zx_status_t GetSlice(size_t index, fvm::slice_entry_t** out) const;
46 
47     fvm::fvm_t* SuperBlock() const;
MetadataSize()48     size_t MetadataSize() const { return metadata_size_; }
DiskSize()49     size_t DiskSize() const { return SuperBlock()->fvm_partition_size; }
SliceSize()50     size_t SliceSize() const { return SuperBlock()->slice_size; }
51 
52     // Returns true if the in-memory metadata has been changed from the original values (i.e.
53     // partitions/slices have been allocated since initialization).
IsDirty()54     bool IsDirty() const { return dirty_; }
55 
56     // Returns true if metadata_ contains valid FVM metadata.
IsValid()57     bool IsValid() const { return valid_; }
58 
59     // Checks whether the metadata is valid, and immediately exits the process if it isn't.
60     void CheckValid() const;
61 
62 private:
63     bool valid_;
64     bool dirty_;
65     size_t metadata_size_;
66     uint32_t vpart_hint_;
67     uint32_t pslice_hint_;
68     fbl::unique_ptr<uint8_t[]> metadata_;
69 };
70