1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <optional>
18 
19 #include <android-base/unique_fd.h>
20 
21 #include <libsnapshot/cow_writer.h>
22 
23 namespace chromeos_update_engine {
24 class FileDescriptor;
25 }  // namespace chromeos_update_engine
26 
27 namespace android {
28 namespace snapshot {
29 
30 class ISnapshotWriter : public ICowWriter {
31   public:
32     using FileDescriptor = chromeos_update_engine::FileDescriptor;
33 
34     explicit ISnapshotWriter(const CowOptions& options);
35 
36     // Set the source device. This is used for AddCopy() operations, if the
37     // underlying writer needs the original bytes (for example if backed by
38     // dm-snapshot or if writing directly to an unsnapshotted region). The
39     // device is only opened on the first operation that requires it.
40     void SetSourceDevice(const std::string& source_device);
41 
42     // Open the writer in write mode (no append).
43     virtual bool Initialize() = 0;
44 
45     // Open the writer in append mode, with the last label to resume
46     // from. See CowWriter::InitializeAppend.
47     virtual bool InitializeAppend(uint64_t label) = 0;
48 
49     virtual std::unique_ptr<FileDescriptor> OpenReader() = 0;
50     virtual bool VerifyMergeOps() const noexcept = 0;
51 
52   protected:
53     android::base::borrowed_fd GetSourceFd();
54 
55     std::optional<std::string> source_device_;
56 
57   private:
58     android::base::unique_fd source_fd_;
59 };
60 
61 // Send writes to a COW or a raw device directly, based on a threshold.
62 class CompressedSnapshotWriter final : public ISnapshotWriter {
63   public:
64     CompressedSnapshotWriter(const CowOptions& options);
65 
66     // Sets the COW device; this is required.
67     bool SetCowDevice(android::base::unique_fd&& cow_device);
68 
69     bool Initialize() override;
70     bool InitializeAppend(uint64_t label) override;
71     bool Finalize() override;
72     uint64_t GetCowSize() override;
73     std::unique_ptr<FileDescriptor> OpenReader() override;
74     bool VerifyMergeOps() const noexcept;
75 
76   protected:
77     bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
78     bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
79     bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
80                        uint16_t offset) override;
81     bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
82     bool EmitLabel(uint64_t label) override;
83     bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
84 
85   private:
86     std::unique_ptr<CowReader> OpenCowReader() const;
87     android::base::unique_fd cow_device_;
88 
89     std::unique_ptr<CowWriter> cow_;
90 };
91 
92 // Write directly to a dm-snapshot device.
93 class OnlineKernelSnapshotWriter final : public ISnapshotWriter {
94   public:
95     OnlineKernelSnapshotWriter(const CowOptions& options);
96 
97     // Set the device used for all writes.
98     void SetSnapshotDevice(android::base::unique_fd&& snapshot_fd, uint64_t cow_size);
99 
Initialize()100     bool Initialize() override { return true; }
InitializeAppend(uint64_t)101     bool InitializeAppend(uint64_t) override { return true; }
102 
103     bool Finalize() override;
GetCowSize()104     uint64_t GetCowSize() override { return cow_size_; }
105     std::unique_ptr<FileDescriptor> OpenReader() override;
106 
107     // Online kernel snapshot writer doesn't care about merge sequences.
108     // So ignore.
VerifyMergeOps()109     bool VerifyMergeOps() const noexcept override { return true; }
110 
111   protected:
112     bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
113     bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
114     bool EmitXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
115                        uint16_t offset) override;
116     bool EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks = 1) override;
117     bool EmitLabel(uint64_t label) override;
118     bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
119 
120   private:
121     android::base::unique_fd snapshot_fd_;
122     uint64_t cow_size_ = 0;
123 };
124 
125 }  // namespace snapshot
126 }  // namespace android
127