• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include <sys/types.h>
18 #include <unistd.h>
19 
20 #include <algorithm>
21 #include <optional>
22 #include <unordered_map>
23 #include <unordered_set>
24 #include <vector>
25 
26 #include <android-base/file.h>
27 #include <android-base/logging.h>
28 #include <libsnapshot/cow_format.h>
29 #include <libsnapshot/cow_reader.h>
30 #include <storage_literals/storage_literals.h>
31 #include <zlib.h>
32 
33 #include "cow_decompress.h"
34 #include "parser_v2.h"
35 #include "parser_v3.h"
36 
37 namespace android {
38 namespace snapshot {
39 
40 using namespace android::storage_literals;
41 
ReadCowHeader(android::base::borrowed_fd fd,CowHeaderV3 * header)42 bool ReadCowHeader(android::base::borrowed_fd fd, CowHeaderV3* header) {
43     if (lseek(fd.get(), 0, SEEK_SET) < 0) {
44         PLOG(ERROR) << "lseek header failed";
45         return false;
46     }
47 
48     memset(header, 0, sizeof(*header));
49 
50     if (!android::base::ReadFully(fd, &header->prefix, sizeof(header->prefix))) {
51         return false;
52     }
53     if (header->prefix.magic != kCowMagicNumber) {
54         LOG(ERROR) << "Header Magic corrupted. Magic: " << header->prefix.magic
55                    << "Expected: " << kCowMagicNumber;
56         return false;
57     }
58     if (header->prefix.header_size > sizeof(CowHeaderV3)) {
59         LOG(ERROR) << "Unknown CowHeader size (got " << header->prefix.header_size
60                    << " bytes, expected at most " << sizeof(CowHeaderV3) << " bytes)";
61         return false;
62     }
63 
64     if (lseek(fd.get(), 0, SEEK_SET) < 0) {
65         PLOG(ERROR) << "lseek header failed";
66         return false;
67     }
68     return android::base::ReadFully(fd, header, header->prefix.header_size);
69 }
70 
CowReader(ReaderFlags reader_flag,bool is_merge)71 CowReader::CowReader(ReaderFlags reader_flag, bool is_merge)
72     : fd_(-1),
73       header_(),
74       fd_size_(0),
75       block_pos_index_(std::make_shared<std::vector<int>>()),
76       reader_flag_(reader_flag),
77       is_merge_(is_merge) {}
78 
CloneCowReader()79 std::unique_ptr<CowReader> CowReader::CloneCowReader() {
80     auto cow = std::make_unique<CowReader>();
81     cow->owned_fd_.reset();
82     cow->header_ = header_;
83     cow->footer_ = footer_;
84     cow->fd_size_ = fd_size_;
85     cow->last_label_ = last_label_;
86     cow->ops_ = ops_;
87     cow->merge_op_start_ = merge_op_start_;
88     cow->num_total_data_ops_ = num_total_data_ops_;
89     cow->num_ordered_ops_to_merge_ = num_ordered_ops_to_merge_;
90     cow->xor_data_loc_ = xor_data_loc_;
91     cow->block_pos_index_ = block_pos_index_;
92     cow->is_merge_ = is_merge_;
93     return cow;
94 }
95 
InitForMerge(android::base::unique_fd && fd)96 bool CowReader::InitForMerge(android::base::unique_fd&& fd) {
97     owned_fd_ = std::move(fd);
98     fd_ = owned_fd_.get();
99 
100     auto pos = lseek(fd_.get(), 0, SEEK_END);
101     if (pos < 0) {
102         PLOG(ERROR) << "lseek end failed";
103         return false;
104     }
105     fd_size_ = pos;
106 
107     if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
108         PLOG(ERROR) << "lseek header failed";
109         return false;
110     }
111 
112     CHECK_GE(header_.prefix.header_size, sizeof(CowHeader));
113     CHECK_LE(header_.prefix.header_size, sizeof(header_));
114 
115     if (!android::base::ReadFully(fd_, &header_, header_.prefix.header_size)) {
116         PLOG(ERROR) << "read header failed";
117         return false;
118     }
119     return true;
120 }
121 
Parse(android::base::unique_fd && fd,std::optional<uint64_t> label)122 bool CowReader::Parse(android::base::unique_fd&& fd, std::optional<uint64_t> label) {
123     owned_fd_ = std::move(fd);
124     return Parse(android::base::borrowed_fd{owned_fd_}, label);
125 }
126 
Parse(android::base::borrowed_fd fd,std::optional<uint64_t> label)127 bool CowReader::Parse(android::base::borrowed_fd fd, std::optional<uint64_t> label) {
128     fd_ = fd;
129 
130     if (!ReadCowHeader(fd, &header_)) {
131         return false;
132     }
133 
134     std::unique_ptr<CowParserBase> parser;
135     switch (header_.prefix.major_version) {
136         case 1:
137         case 2:
138             parser = std::make_unique<CowParserV2>();
139             break;
140         case 3:
141             parser = std::make_unique<CowParserV3>();
142             break;
143         default:
144             LOG(ERROR) << "Unknown version: " << header_.prefix.major_version;
145             return false;
146     }
147     if (!parser->Parse(fd, header_, label)) {
148         return false;
149     }
150 
151     TranslatedCowOps ops_info;
152     if (!parser->Translate(&ops_info)) {
153         return false;
154     }
155 
156     header_ = ops_info.header;
157     ops_ = std::move(ops_info.ops);
158     footer_ = parser->footer();
159     fd_size_ = parser->fd_size();
160     last_label_ = parser->last_label();
161     xor_data_loc_ = parser->xor_data_loc();
162 
163     // If we're resuming a write, we're not ready to merge
164     if (label.has_value()) return true;
165     return PrepMergeOps();
166 }
167 
GetMaxCompressionSize()168 uint32_t CowReader::GetMaxCompressionSize() {
169     switch (header_.prefix.major_version) {
170         case 1:
171         case 2:
172             // Old versions supports only 4KB compression.
173             return header_.block_size;
174             ;
175         case 3:
176             return header_.max_compression_size;
177         default:
178             LOG(ERROR) << "Unknown version: " << header_.prefix.major_version;
179             return 0;
180     }
181 }
182 
183 //
184 // This sets up the data needed for MergeOpIter. MergeOpIter presents
185 // data in the order we intend to merge in.
186 //
187 // We merge all order sensitive ops up front, and sort the rest to allow for
188 // batch merging. Order sensitive ops can either be presented in their proper
189 // order in the cow, or be ordered by sequence ops (kCowSequenceOp), in which
190 // case we want to merge those ops first, followed by any ops not specified by
191 // new_block value by the sequence op, in sorted order.
192 // We will re-arrange the vector in such a way that
193 // kernel can batch merge. Ex:
194 //
195 // Existing COW format; All the copy operations
196 // are at the beginning.
197 // =======================================
198 // Copy-op-1    - cow_op->new_block = 1
199 // Copy-op-2    - cow_op->new_block = 2
200 // Copy-op-3    - cow_op->new_block = 3
201 // Replace-op-4 - cow_op->new_block = 6
202 // Replace-op-5 - cow_op->new_block = 4
203 // Replace-op-6 - cow_op->new_block = 8
204 // Replace-op-7 - cow_op->new_block = 9
205 // Zero-op-8    - cow_op->new_block = 7
206 // Zero-op-9    - cow_op->new_block = 5
207 // =======================================
208 //
209 // First find the operation which isn't a copy-op
210 // and then sort all the operations in descending order
211 // with the key being cow_op->new_block (source block)
212 //
213 // The data-structure will look like:
214 //
215 // =======================================
216 // Copy-op-1    - cow_op->new_block = 1
217 // Copy-op-2    - cow_op->new_block = 2
218 // Copy-op-3    - cow_op->new_block = 3
219 // Replace-op-7 - cow_op->new_block = 9
220 // Replace-op-6 - cow_op->new_block = 8
221 // Zero-op-8    - cow_op->new_block = 7
222 // Replace-op-4 - cow_op->new_block = 6
223 // Zero-op-9    - cow_op->new_block = 5
224 // Replace-op-5 - cow_op->new_block = 4
225 // =======================================
226 //
227 // Daemon will read the above data-structure in reverse-order
228 // when reading metadata. Thus, kernel will get the metadata
229 // in the following order:
230 //
231 // ========================================
232 // Replace-op-5 - cow_op->new_block = 4
233 // Zero-op-9    - cow_op->new_block = 5
234 // Replace-op-4 - cow_op->new_block = 6
235 // Zero-op-8    - cow_op->new_block = 7
236 // Replace-op-6 - cow_op->new_block = 8
237 // Replace-op-7 - cow_op->new_block = 9
238 // Copy-op-3    - cow_op->new_block = 3
239 // Copy-op-2    - cow_op->new_block = 2
240 // Copy-op-1    - cow_op->new_block = 1
241 // ===========================================
242 //
243 // When merging begins, kernel will start from the last
244 // metadata which was read: In the above format, Copy-op-1
245 // will be the first merge operation.
246 //
247 // Now, batching of the merge operations happens only when
248 // 1: origin block numbers in the base device are contiguous
249 // (cow_op->new_block) and,
250 // 2: cow block numbers which are assigned by daemon in ReadMetadata()
251 // are contiguous. These are monotonically increasing numbers.
252 //
253 // When both (1) and (2) are true, kernel will batch merge the operations.
254 // In the above case, we have to ensure that the copy operations
255 // are merged first before replace operations are done. Hence,
256 // we will not change the order of copy operations. Since,
257 // cow_op->new_block numbers are contiguous, we will ensure that the
258 // cow block numbers assigned in ReadMetadata() for these respective copy
259 // operations are not contiguous forcing kernel to issue merge for each
260 // copy operations without batch merging.
261 //
262 // For all the other operations viz. Replace and Zero op, the cow block
263 // numbers assigned by daemon will be contiguous allowing kernel to batch
264 // merge.
265 //
266 // The final format after assiging COW block numbers by the daemon will
267 // look something like:
268 //
269 // =========================================================
270 // Replace-op-5 - cow_op->new_block = 4  cow-block-num = 2
271 // Zero-op-9    - cow_op->new_block = 5  cow-block-num = 3
272 // Replace-op-4 - cow_op->new_block = 6  cow-block-num = 4
273 // Zero-op-8    - cow_op->new_block = 7  cow-block-num = 5
274 // Replace-op-6 - cow_op->new_block = 8  cow-block-num = 6
275 // Replace-op-7 - cow_op->new_block = 9  cow-block-num = 7
276 // Copy-op-3    - cow_op->new_block = 3  cow-block-num = 9
277 // Copy-op-2    - cow_op->new_block = 2  cow-block-num = 11
278 // Copy-op-1    - cow_op->new_block = 1  cow-block-num = 13
279 // ==========================================================
280 //
281 // Merge sequence will look like:
282 //
283 // Merge-1 - Batch-merge { Copy-op-1, Copy-op-2, Copy-op-3 }
284 // Merge-2 - Batch-merge {Replace-op-7, Replace-op-6, Zero-op-8,
285 //                        Replace-op-4, Zero-op-9, Replace-op-5 }
286 //==============================================================
PrepMergeOps()287 bool CowReader::PrepMergeOps() {
288     std::vector<int> other_ops;
289     std::vector<uint32_t> merge_op_blocks;
290     std::unordered_map<uint32_t, int> block_map;
291 
292     switch (header_.prefix.major_version) {
293         case 1:
294         case 2:
295             GetSequenceDataV2(&merge_op_blocks, &other_ops, &block_map);
296             break;
297         case 3:
298             GetSequenceData(&merge_op_blocks, &other_ops, &block_map);
299             break;
300         default:
301             break;
302     }
303 
304     for (auto block : merge_op_blocks) {
305         if (block_map.count(block) == 0) {
306             LOG(ERROR) << "Invalid Sequence Ops. Could not find Cow Op for new block " << block;
307             return false;
308         }
309     }
310 
311     if (merge_op_blocks.size() > header_.num_merge_ops) {
312         num_ordered_ops_to_merge_ = merge_op_blocks.size() - header_.num_merge_ops;
313     } else {
314         num_ordered_ops_to_merge_ = 0;
315     }
316 
317     // Sort the vector in increasing order if merging in user-space as
318     // we can batch merge them when iterating from forward.
319     //
320     // dm-snapshot-merge requires decreasing order as we iterate the blocks
321     // in reverse order.
322     if (reader_flag_ == ReaderFlags::USERSPACE_MERGE) {
323         std::sort(other_ops.begin(), other_ops.end());
324     } else {
325         std::sort(other_ops.begin(), other_ops.end(), std::greater<int>());
326     }
327 
328     merge_op_blocks.insert(merge_op_blocks.end(), other_ops.begin(), other_ops.end());
329 
330     num_total_data_ops_ = merge_op_blocks.size();
331     if (header_.num_merge_ops > 0) {
332         merge_op_start_ = header_.num_merge_ops;
333     }
334 
335     if (is_merge_) {
336         // Metadata ops are not required for merge. Thus, just re-arrange
337         // the ops vector as required for merge operations.
338         auto merge_ops_buffer = std::make_shared<std::vector<CowOperation>>();
339         merge_ops_buffer->reserve(num_total_data_ops_);
340         for (auto block : merge_op_blocks) {
341             merge_ops_buffer->emplace_back(ops_->data()[block_map.at(block)]);
342         }
343         ops_->clear();
344         ops_ = merge_ops_buffer;
345         ops_->shrink_to_fit();
346     } else {
347         for (auto block : merge_op_blocks) {
348             block_pos_index_->push_back(block_map.at(block));
349         }
350     }
351 
352     block_map.clear();
353     merge_op_blocks.clear();
354 
355     return true;
356 }
357 
GetSequenceDataV2(std::vector<uint32_t> * merge_op_blocks,std::vector<int> * other_ops,std::unordered_map<uint32_t,int> * block_map)358 bool CowReader::GetSequenceDataV2(std::vector<uint32_t>* merge_op_blocks,
359                                   std::vector<int>* other_ops,
360                                   std::unordered_map<uint32_t, int>* block_map) {
361     auto seq_ops_set = std::unordered_set<uint32_t>();
362     size_t num_seqs = 0;
363     size_t read;
364     for (size_t i = 0; i < ops_->size(); i++) {
365         auto& current_op = ops_->data()[i];
366 
367         if (current_op.type() == kCowSequenceOp) {
368             size_t seq_len = current_op.data_length / sizeof(uint32_t);
369 
370             merge_op_blocks->resize(merge_op_blocks->size() + seq_len);
371             if (!GetRawBytes(&current_op, &merge_op_blocks->data()[num_seqs],
372                              current_op.data_length, &read)) {
373                 PLOG(ERROR) << "Failed to read sequence op!";
374                 return false;
375             }
376             for (size_t j = num_seqs; j < num_seqs + seq_len; j++) {
377                 seq_ops_set.insert(merge_op_blocks->at(j));
378             }
379             num_seqs += seq_len;
380         }
381 
382         if (IsMetadataOp(current_op)) {
383             continue;
384         }
385 
386         // Sequence ops must be the first ops in the stream.
387         if (seq_ops_set.empty() && IsOrderedOp(current_op)) {
388             merge_op_blocks->emplace_back(current_op.new_block);
389         } else if (seq_ops_set.count(current_op.new_block) == 0) {
390             other_ops->push_back(current_op.new_block);
391         }
392         block_map->insert({current_op.new_block, i});
393     }
394     return false;
395 }
396 
GetSequenceData(std::vector<uint32_t> * merge_op_blocks,std::vector<int> * other_ops,std::unordered_map<uint32_t,int> * block_map)397 bool CowReader::GetSequenceData(std::vector<uint32_t>* merge_op_blocks, std::vector<int>* other_ops,
398                                 std::unordered_map<uint32_t, int>* block_map) {
399     std::unordered_set<uint32_t> seq_ops_set;
400     // read sequence ops data
401     merge_op_blocks->resize(header_.sequence_data_count);
402     if (!android::base::ReadFullyAtOffset(
403                 fd_, merge_op_blocks->data(),
404                 header_.sequence_data_count * sizeof(merge_op_blocks->at(0)),
405                 GetSequenceOffset(header_))) {
406         PLOG(ERROR) << "failed to read sequence buffer. seq_data_count: "
407                     << header_.sequence_data_count << " at offset: " << GetSequenceOffset(header_);
408         return false;
409     }
410     seq_ops_set.reserve(merge_op_blocks->size());
411     for (auto& i : *merge_op_blocks) {
412         seq_ops_set.insert(i);
413     }
414     // read ordered op data
415     for (size_t i = 0; i < ops_->size(); i++) {
416         auto& current_op = ops_->data()[i];
417         // Sequence ops must be the first ops in the stream.
418         if (seq_ops_set.empty()) {
419             merge_op_blocks->emplace_back(current_op.new_block);
420         } else if (seq_ops_set.count(current_op.new_block) == 0) {
421             other_ops->push_back(current_op.new_block);
422         }
423         block_map->insert({current_op.new_block, i});
424     }
425     return true;
426 }
427 
VerifyMergeOps()428 bool CowReader::VerifyMergeOps() {
429     auto itr = GetMergeOpIter(true);
430     std::unordered_map<uint64_t, const CowOperation*> overwritten_blocks;
431     bool non_ordered_op_found = false;
432 
433     while (!itr->AtEnd()) {
434         const auto& op = itr->Get();
435         uint64_t offset;
436 
437         // Op should not be a metadata
438         if (IsMetadataOp(*op)) {
439             LOG(ERROR) << "Metadata op: " << op << " found during merge sequence";
440             return false;
441         }
442 
443         // Sequence ops should contain all the ordered ops followed
444         // by Replace and Zero ops. If we find the first op which
445         // is not ordered, that means all ordered ops processing
446         // has been completed.
447         if (!IsOrderedOp(*op)) {
448             non_ordered_op_found = true;
449         }
450 
451         // Since, all ordered ops processing has been completed,
452         // check that the subsequent ops are not ordered.
453         if (non_ordered_op_found && IsOrderedOp(*op)) {
454             LOG(ERROR) << "Invalid sequence - non-ordered and ordered ops"
455                        << " cannot be mixed during sequence generation";
456             return false;
457         }
458 
459         if (!GetSourceOffset(op, &offset)) {
460             itr->Next();
461             continue;
462         }
463 
464         uint64_t block = GetBlockFromOffset(header_, offset);
465         bool misaligned = (GetBlockRelativeOffset(header_, offset) != 0);
466 
467         const CowOperation* overwrite = nullptr;
468         if (overwritten_blocks.count(block)) {
469             overwrite = overwritten_blocks[block];
470             LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
471                        << op << "\noverwritten by previously merged op:\n"
472                        << *overwrite;
473         }
474         if (misaligned && overwritten_blocks.count(block + 1)) {
475             overwrite = overwritten_blocks[block + 1];
476             LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
477                        << op << "\noverwritten by previously merged op:\n"
478                        << *overwrite;
479         }
480         if (overwrite != nullptr) return false;
481         overwritten_blocks[op->new_block] = op;
482         itr->Next();
483     }
484     return true;
485 }
486 
GetFooter(CowFooter * footer)487 bool CowReader::GetFooter(CowFooter* footer) {
488     if (!footer_) return false;
489     *footer = footer_.value();
490     return true;
491 }
492 
GetLastLabel(uint64_t * label)493 bool CowReader::GetLastLabel(uint64_t* label) {
494     if (!last_label_) return false;
495     *label = last_label_.value();
496     return true;
497 }
498 
499 class CowOpIter final : public ICowOpIter {
500   public:
501     CowOpIter(std::shared_ptr<std::vector<CowOperation>>& ops, uint64_t start);
502 
503     bool AtEnd() override;
504     const CowOperation* Get() override;
505     void Next() override;
506 
507     void Prev() override;
508     bool AtBegin() override;
509 
510   private:
511     std::shared_ptr<std::vector<CowOperation>> ops_;
512     std::vector<CowOperation>::iterator op_iter_;
513 };
514 
CowOpIter(std::shared_ptr<std::vector<CowOperation>> & ops,uint64_t start)515 CowOpIter::CowOpIter(std::shared_ptr<std::vector<CowOperation>>& ops, uint64_t start) {
516     ops_ = ops;
517     op_iter_ = ops_->begin() + start;
518 }
519 
AtBegin()520 bool CowOpIter::AtBegin() {
521     return op_iter_ == ops_->begin();
522 }
523 
Prev()524 void CowOpIter::Prev() {
525     CHECK(!AtBegin());
526     op_iter_--;
527 }
528 
AtEnd()529 bool CowOpIter::AtEnd() {
530     return op_iter_ == ops_->end();
531 }
532 
Next()533 void CowOpIter::Next() {
534     CHECK(!AtEnd());
535     op_iter_++;
536 }
537 
Get()538 const CowOperation* CowOpIter::Get() {
539     CHECK(!AtEnd());
540     return &(*op_iter_);
541 }
542 
543 class CowRevMergeOpIter final : public ICowOpIter {
544   public:
545     explicit CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
546                                std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
547 
548     bool AtEnd() override;
549     const CowOperation* Get() override;
550     void Next() override;
551 
552     void Prev() override;
553     bool AtBegin() override;
554 
555   private:
556     std::shared_ptr<std::vector<CowOperation>> ops_;
557     std::vector<int>::reverse_iterator block_riter_;
558     std::shared_ptr<std::vector<int>> cow_op_index_vec_;
559     uint64_t start_;
560 };
561 
562 class CowMergeOpIter final : public ICowOpIter {
563   public:
564     explicit CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
565                             std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
566 
567     bool AtEnd() override;
568     const CowOperation* Get() override;
569     void Next() override;
570 
571     void Prev() override;
572     bool AtBegin() override;
573 
574   private:
575     std::shared_ptr<std::vector<CowOperation>> ops_;
576     std::vector<int>::iterator block_iter_;
577     std::shared_ptr<std::vector<int>> cow_op_index_vec_;
578     uint64_t start_;
579 };
580 
CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,std::shared_ptr<std::vector<int>> block_pos_index,uint64_t start)581 CowMergeOpIter::CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
582                                std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start) {
583     ops_ = ops;
584     start_ = start;
585     cow_op_index_vec_ = block_pos_index;
586     block_iter_ = cow_op_index_vec_->begin() + start;
587 }
588 
AtBegin()589 bool CowMergeOpIter::AtBegin() {
590     return block_iter_ == cow_op_index_vec_->begin();
591 }
592 
Prev()593 void CowMergeOpIter::Prev() {
594     CHECK(!AtBegin());
595     block_iter_--;
596 }
597 
AtEnd()598 bool CowMergeOpIter::AtEnd() {
599     return block_iter_ == cow_op_index_vec_->end();
600 }
601 
Next()602 void CowMergeOpIter::Next() {
603     CHECK(!AtEnd());
604     block_iter_++;
605 }
606 
Get()607 const CowOperation* CowMergeOpIter::Get() {
608     CHECK(!AtEnd());
609     return &ops_->data()[*block_iter_];
610 }
611 
CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,std::shared_ptr<std::vector<int>> block_pos_index,uint64_t start)612 CowRevMergeOpIter::CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
613                                      std::shared_ptr<std::vector<int>> block_pos_index,
614                                      uint64_t start) {
615     ops_ = ops;
616     start_ = start;
617     cow_op_index_vec_ = block_pos_index;
618     block_riter_ = cow_op_index_vec_->rbegin();
619 }
620 
AtBegin()621 bool CowRevMergeOpIter::AtBegin() {
622     return block_riter_ == cow_op_index_vec_->rbegin();
623 }
624 
Prev()625 void CowRevMergeOpIter::Prev() {
626     CHECK(!AtBegin());
627     block_riter_--;
628 }
629 
AtEnd()630 bool CowRevMergeOpIter::AtEnd() {
631     return block_riter_ == cow_op_index_vec_->rend() - start_;
632 }
633 
Next()634 void CowRevMergeOpIter::Next() {
635     CHECK(!AtEnd());
636     block_riter_++;
637 }
638 
Get()639 const CowOperation* CowRevMergeOpIter::Get() {
640     CHECK(!AtEnd());
641     return &ops_->data()[*block_riter_];
642 }
643 
GetOpIter(bool merge_progress)644 std::unique_ptr<ICowOpIter> CowReader::GetOpIter(bool merge_progress) {
645     return std::make_unique<CowOpIter>(ops_, merge_progress ? merge_op_start_ : 0);
646 }
647 
GetRevMergeOpIter(bool ignore_progress)648 std::unique_ptr<ICowOpIter> CowReader::GetRevMergeOpIter(bool ignore_progress) {
649     return std::make_unique<CowRevMergeOpIter>(ops_, block_pos_index_,
650                                                ignore_progress ? 0 : merge_op_start_);
651 }
652 
GetMergeOpIter(bool ignore_progress)653 std::unique_ptr<ICowOpIter> CowReader::GetMergeOpIter(bool ignore_progress) {
654     return std::make_unique<CowMergeOpIter>(ops_, block_pos_index_,
655                                             ignore_progress ? 0 : merge_op_start_);
656 }
657 
GetRawBytes(const CowOperation * op,void * buffer,size_t len,size_t * read)658 bool CowReader::GetRawBytes(const CowOperation* op, void* buffer, size_t len, size_t* read) {
659     switch (op->type()) {
660         case kCowSequenceOp:
661         case kCowReplaceOp:
662         case kCowXorOp:
663             return GetRawBytes(op->source(), buffer, len, read);
664         default:
665             LOG(ERROR) << "Cannot get raw bytes of non-data op: " << *op;
666             return false;
667     }
668 }
669 
GetRawBytes(uint64_t offset,void * buffer,size_t len,size_t * read)670 bool CowReader::GetRawBytes(uint64_t offset, void* buffer, size_t len, size_t* read) {
671     // Validate the offset, taking care to acknowledge possible overflow of offset+len.
672     if (offset < header_.prefix.header_size || offset >= fd_size_ || offset + len > fd_size_ ||
673         len >= fd_size_) {
674         LOG(ERROR) << "invalid data offset: " << offset << ", " << len << " bytes";
675         return false;
676     }
677     if (lseek(fd_.get(), offset, SEEK_SET) < 0) {
678         PLOG(ERROR) << "lseek to read raw bytes failed";
679         return false;
680     }
681     ssize_t rv = TEMP_FAILURE_RETRY(::read(fd_.get(), buffer, len));
682     if (rv < 0) {
683         PLOG(ERROR) << "read failed";
684         return false;
685     }
686     *read = rv;
687     return true;
688 }
689 
690 class CowDataStream final : public IByteStream {
691   public:
CowDataStream(CowReader * reader,uint64_t offset,size_t data_length)692     CowDataStream(CowReader* reader, uint64_t offset, size_t data_length)
693         : reader_(reader), offset_(offset), data_length_(data_length) {
694         remaining_ = data_length_;
695     }
696 
Read(void * buffer,size_t length)697     ssize_t Read(void* buffer, size_t length) override {
698         size_t to_read = std::min(length, remaining_);
699         if (!to_read) {
700             return 0;
701         }
702         size_t read;
703         if (!reader_->GetRawBytes(offset_, buffer, to_read, &read)) {
704             return -1;
705         }
706         offset_ += read;
707         remaining_ -= read;
708         return read;
709     }
710 
Size() const711     size_t Size() const override { return data_length_; }
712 
713   private:
714     CowReader* reader_;
715     uint64_t offset_;
716     size_t data_length_;
717     size_t remaining_;
718 };
719 
GetCompressionType()720 uint8_t CowReader::GetCompressionType() {
721     return header_.compression_algorithm;
722 }
723 
ReadData(const CowOperation * op,void * buffer,size_t buffer_size,size_t ignore_bytes)724 ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
725                             size_t ignore_bytes) {
726     std::unique_ptr<IDecompressor> decompressor;
727     const size_t op_buf_size = CowOpCompressionSize(op, header_.block_size);
728     if (!op_buf_size) {
729         LOG(ERROR) << "Compression size is zero. op: " << *op;
730         return -1;
731     }
732     switch (GetCompressionType()) {
733         case kCowCompressNone:
734             break;
735         case kCowCompressGz:
736             decompressor = IDecompressor::Gz();
737             break;
738         case kCowCompressBrotli:
739             decompressor = IDecompressor::Brotli();
740             break;
741         case kCowCompressZstd:
742             if (op_buf_size != op->data_length) {
743                 decompressor = IDecompressor::Zstd();
744             }
745             break;
746         case kCowCompressLz4:
747             if (op_buf_size != op->data_length) {
748                 decompressor = IDecompressor::Lz4();
749             }
750             break;
751         default:
752             LOG(ERROR) << "Unknown compression type: " << GetCompressionType();
753             return -1;
754     }
755 
756     uint64_t offset;
757     if (op->type() == kCowXorOp) {
758         offset = xor_data_loc_->at(op->new_block);
759     } else {
760         offset = op->source();
761     }
762     if (!decompressor ||
763         ((op->data_length == op_buf_size) && (header_.prefix.major_version == 3))) {
764         CowDataStream stream(this, offset + ignore_bytes, op->data_length - ignore_bytes);
765         return stream.ReadFully(buffer, buffer_size);
766     }
767 
768     CowDataStream stream(this, offset, op->data_length);
769     decompressor->set_stream(&stream);
770     return decompressor->Decompress(buffer, buffer_size, op_buf_size, ignore_bytes);
771 }
772 
GetSourceOffset(const CowOperation * op,uint64_t * source_offset)773 bool CowReader::GetSourceOffset(const CowOperation* op, uint64_t* source_offset) {
774     switch (op->type()) {
775         case kCowCopyOp:
776             *source_offset = op->source() * header_.block_size;
777             return true;
778         case kCowXorOp:
779             *source_offset = op->source();
780             return true;
781         default:
782             return false;
783     }
784 }
785 
786 }  // namespace snapshot
787 }  // namespace android
788