blob: bf5ce8bb56fc1f0f943c1a885ab47a2446d5e36a [file] [log] [blame]
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <optional>
#include <android-base/unique_fd.h>
#include <libsnapshot/cow_writer.h>
namespace chromeos_update_engine {
class FileDescriptor;
} // namespace chromeos_update_engine
namespace android {
namespace snapshot {
class ISnapshotWriter : public ICowWriter {
public:
using FileDescriptor = chromeos_update_engine::FileDescriptor;
explicit ISnapshotWriter(const CowOptions& options);
// Set the source device. This is used for AddCopy() operations, if the
// underlying writer needs the original bytes (for example if backed by
// dm-snapshot or if writing directly to an unsnapshotted region). The
// device is only opened on the first operation that requires it.
void SetSourceDevice(const std::string& source_device);
// Open the writer in write mode (no append).
virtual bool Initialize() = 0;
// Open the writer in append mode, with the last label to resume
// from. See CowWriter::InitializeAppend.
virtual bool InitializeAppend(uint64_t label) = 0;
virtual std::unique_ptr<FileDescriptor> OpenReader() = 0;
protected:
android::base::borrowed_fd GetSourceFd();
std::optional<std::string> source_device_;
private:
android::base::unique_fd source_fd_;
};
// Send writes to a COW or a raw device directly, based on a threshold.
class CompressedSnapshotWriter : public ISnapshotWriter {
public:
CompressedSnapshotWriter(const CowOptions& options);
// Sets the COW device; this is required.
bool SetCowDevice(android::base::unique_fd&& cow_device);
bool Initialize() override;
bool InitializeAppend(uint64_t label) override;
bool Finalize() override;
uint64_t GetCowSize() override;
std::unique_ptr<FileDescriptor> OpenReader() override;
protected:
bool EmitCopy(uint64_t new_block, uint64_t old_block) override;
bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
bool EmitLabel(uint64_t label) override;
private:
android::base::unique_fd cow_device_;
std::unique_ptr<CowWriter> cow_;
};
// Write directly to a dm-snapshot device.
class OnlineKernelSnapshotWriter : public ISnapshotWriter {
public:
OnlineKernelSnapshotWriter(const CowOptions& options);
// Set the device used for all writes.
void SetSnapshotDevice(android::base::unique_fd&& snapshot_fd, uint64_t cow_size);
bool Initialize() override { return true; }
bool InitializeAppend(uint64_t) override { return true; }
bool Finalize() override;
uint64_t GetCowSize() override { return cow_size_; }
std::unique_ptr<FileDescriptor> OpenReader() override;
protected:
bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
bool EmitCopy(uint64_t new_block, uint64_t old_block) override;
bool EmitLabel(uint64_t label) override;
private:
android::base::unique_fd snapshot_fd_;
uint64_t cow_size_ = 0;
};
} // namespace snapshot
} // namespace android