diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp index 5306b2843..20030b940 100644 --- a/fs_mgr/libsnapshot/cow_reader.cpp +++ b/fs_mgr/libsnapshot/cow_reader.cpp @@ -34,11 +34,12 @@ namespace android { namespace snapshot { -CowReader::CowReader() +CowReader::CowReader(ReaderFlags reader_flag) : fd_(-1), header_(), fd_size_(0), - merge_op_blocks_(std::make_shared>()) {} + merge_op_blocks_(std::make_shared>()), + reader_flag_(reader_flag) {} static void SHA256(const void*, size_t, uint8_t[]) { #if 0 @@ -415,7 +416,7 @@ bool CowReader::ParseOps(std::optional label) { //============================================================== bool CowReader::PrepMergeOps() { auto merge_op_blocks = std::make_shared>(); - std::set> other_ops; + std::vector other_ops; auto seq_ops_set = std::unordered_set(); auto block_map = std::make_shared>(); size_t num_seqs = 0; @@ -446,7 +447,7 @@ bool CowReader::PrepMergeOps() { if (!has_seq_ops_ && IsOrderedOp(current_op)) { merge_op_blocks->emplace_back(current_op.new_block); } else if (seq_ops_set.count(current_op.new_block) == 0) { - other_ops.insert(current_op.new_block); + other_ops.push_back(current_op.new_block); } block_map->insert({current_op.new_block, i}); } @@ -462,6 +463,18 @@ bool CowReader::PrepMergeOps() { } else { num_ordered_ops_to_merge_ = 0; } + + // Sort the vector in increasing order if merging in user-space as + // we can batch merge them when iterating from forward. + // + // dm-snapshot-merge requires decreasing order as we iterate the blocks + // in reverse order. + if (reader_flag_ == ReaderFlags::USERSPACE_MERGE) { + std::sort(other_ops.begin(), other_ops.end()); + } else { + std::sort(other_ops.begin(), other_ops.end(), std::greater()); + } + merge_op_blocks->reserve(merge_op_blocks->size() + other_ops.size()); for (auto block : other_ops) { merge_op_blocks->emplace_back(block); diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h index 63a9e687a..d5b433531 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h @@ -104,7 +104,12 @@ class ICowOpIter { class CowReader final : public ICowReader { public: - CowReader(); + enum class ReaderFlags { + DEFAULT = 0, + USERSPACE_MERGE = 1, + }; + + CowReader(ReaderFlags reader_flag = ReaderFlags::DEFAULT); ~CowReader() { owned_fd_ = {}; } // Parse the COW, optionally, up to the given label. If no label is @@ -166,6 +171,7 @@ class CowReader final : public ICowReader { uint64_t num_ordered_ops_to_merge_; bool has_seq_ops_; std::shared_ptr> data_loc_; + ReaderFlags reader_flag_; }; } // namespace snapshot diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp index 4f32f696d..57e47e7ed 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp @@ -139,7 +139,7 @@ void SnapshotHandler::CheckMergeCompletionStatus() { } bool SnapshotHandler::ReadMetadata() { - reader_ = std::make_unique(); + reader_ = std::make_unique(CowReader::ReaderFlags::USERSPACE_MERGE); CowHeader header; CowOptions options;