blob: 67007adc82f1e592dafd48453ac2aaa7737ac6ce [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_HOST_SPARSE_CONTAINER_H_
#define SRC_STORAGE_FVM_HOST_SPARSE_CONTAINER_H_
#include "src/storage/fvm/host/container.h"
// Function pointer type which operates on partitions that ranges between [|start|, |end|).
// extent_lengths are lengths of each extents in bytes. |out| contains a unit which is dependent on
// the function called.
typedef zx_status_t(UsedSize_f)(const fbl::unique_fd& fd, off_t start, off_t end,
const fbl::Vector<size_t>& extent_lengths, disk_format_t part,
uint64_t* out);
class SparseContainer final : public Container {
public:
// Creates a new SparseContainer at the given |path|, regardless of whether one already exists.
// Uses the provided |slice_size| and |flags| to create the container and returns the result in
// |out|.
static zx_status_t CreateNew(const char* path, size_t slice_size, uint32_t flags,
std::unique_ptr<SparseContainer>* out);
// Creates a new SparseContainer at the given |path|, regardless of whether one already exists.
// Uses the provided |slice_size|, |max_disk_size| and |flags| to create the container and returns
// the result in |out|.
static zx_status_t CreateNew(const char* path, size_t slice_size, uint32_t flags,
uint64_t max_disk_size, std::unique_ptr<SparseContainer>* out);
// Creates a SparseContainer from the image located at |path|. Fails if a valid image does not
// already exist.
static zx_status_t CreateExisting(const char* path, std::unique_ptr<SparseContainer>* out);
~SparseContainer();
// Returns the maximum disk size the FVM will be able to address. This allows preallocating
// metadata storage when formatting an FVM.
uint64_t MaximumDiskSize() const;
zx_status_t Verify() const final;
// On success, returns ZX_OK and copies the number of bytes used by data within the fs.
zx_status_t UsedDataSize(uint64_t* out_size) const;
// On success, returns ZX_OK and copies the number allocated inodes within the fs.
zx_status_t UsedInodes(uint64_t* out_inodes) const;
// On success, returns ZX_OK and copies the number of bytes used by data and bytes reserved for
// superblock, bitmaps, inodes and journal within the fs.
zx_status_t UsedSize(uint64_t* out_size) const;
zx_status_t Commit() final;
// Unpacks the sparse container and "paves" it to the file system exposed by |wrapper|.
zx_status_t Pave(std::unique_ptr<fvm::host::FileWrapper> wrapper, size_t disk_offset = 0,
size_t disk_size = 0);
size_t SliceSize() const final;
size_t SliceCount() const;
zx_status_t AddPartition(const char* path, const char* type_name, FvmReservation* reserve) final;
zx_status_t AddSnapshotMetadataPartition(size_t reserved_slices) final;
// Decompresses the contents of the sparse file (if they are compressed), and writes the output
// to |path|.
zx_status_t Decompress(const char* path);
uint64_t CalculateDiskSize() const final;
// Checks whether the container will fit within a disk of size |target_size| (in bytes).
zx_status_t CheckDiskSize(uint64_t target_size) const;
// Creates a partition of a given size and type, rounded to nearest slice. This is,
// will allocate minimum amount of slices and the rest for the data region.
zx_status_t AddCorruptedPartition(const char* type, uint64_t required_size) final;
private:
bool valid_;
bool dirty_;
size_t disk_size_;
size_t extent_size_;
fvm::SparseImage image_;
fbl::Vector<SparsePartitionInfo> partitions_;
CompressionContext compression_;
std::unique_ptr<fvm::SparseReader> reader_;
SparseContainer(const char* path, uint64_t slice_size, uint32_t flags);
// Resets the SparseContainer state so we are ready to add a new set of partitions.
zx_status_t InitNew();
// Reads sparse data from disk so we are able to inspect the existing container.
zx_status_t InitExisting();
zx_status_t AllocatePartition(std::unique_ptr<Format> format, FvmReservation* reserve);
zx_status_t AllocateExtent(uint32_t part_index, fvm::ExtentDescriptor extent);
zx_status_t PrepareWrite(size_t max_len);
zx_status_t WriteData(const void* data, size_t length);
zx_status_t WriteZeroes(size_t length);
zx_status_t CompleteWrite();
// Calls |used_size_f| on fvm partitions that contain a successfully detected format (through
// Format::Detect()). |out| has a unit which is dependent on the function called.
zx_status_t PartitionsIterator(UsedSize_f* used_size_f, uint64_t* out) const;
void CheckValid() const;
fvm::Header GetFvmConfiguration(uint64_t target_disk_size) const;
};
#endif // SRC_STORAGE_FVM_HOST_SPARSE_CONTAINER_H_