Write cow merge sequence at beginning of update am: a37aafc80f
Original change: https://android-review.googlesource.com/c/platform/system/update_engine/+/1736934
Change-Id: I1d9a75c4ac5778d58341e94e5575b1609d4c18ca
diff --git a/payload_consumer/partition_writer_factory_android.cc b/payload_consumer/partition_writer_factory_android.cc
index 0a9a3fb..6736620 100644
--- a/payload_consumer/partition_writer_factory_android.cc
+++ b/payload_consumer/partition_writer_factory_android.cc
@@ -35,11 +35,8 @@
LOG(INFO)
<< "Virtual AB Compression Enabled, using VABC Partition Writer for `"
<< install_part.name << '`';
- return std::make_unique<VABCPartitionWriter>(partition_update,
- install_part,
- dynamic_control,
- block_size,
- is_interactive);
+ return std::make_unique<VABCPartitionWriter>(
+ partition_update, install_part, dynamic_control, block_size);
} else {
LOG(INFO) << "Virtual AB Compression disabled, using Partition Writer for `"
<< install_part.name << '`';
diff --git a/payload_consumer/vabc_partition_writer.cc b/payload_consumer/vabc_partition_writer.cc
index d181c75..5130d7a 100644
--- a/payload_consumer/vabc_partition_writer.cc
+++ b/payload_consumer/vabc_partition_writer.cc
@@ -30,6 +30,9 @@
#include "update_engine/payload_consumer/install_plan.h"
#include "update_engine/payload_consumer/partition_writer.h"
#include "update_engine/payload_consumer/snapshot_extent_writer.h"
+#include "update_engine/payload_generator/extent_ranges.h"
+#include "update_engine/payload_generator/extent_utils.h"
+#include "update_engine/update_metadata.pb.h"
namespace chromeos_update_engine {
// Expected layout of COW file:
@@ -56,16 +59,17 @@
// label 3, Which contains all operation 2's data, but none of operation 3's
// data.
+using android::snapshot::ICowWriter;
+using ::google::protobuf::RepeatedPtrField;
+
VABCPartitionWriter::VABCPartitionWriter(
const PartitionUpdate& partition_update,
const InstallPlan::Partition& install_part,
DynamicPartitionControlInterface* dynamic_control,
- size_t block_size,
- bool is_interactive)
+ size_t block_size)
: partition_update_(partition_update),
install_part_(install_part),
dynamic_control_(dynamic_control),
- interactive_(is_interactive),
block_size_(block_size),
executor_(block_size),
verified_source_fd_(block_size, install_part.source_path) {}
@@ -101,8 +105,14 @@
}
// ==============================================
+ if (!partition_update_.merge_operations().empty()) {
+ TEST_AND_RETURN_FALSE(WriteMergeSequence(
+ partition_update_.merge_operations(), cow_writer_.get()));
+ }
// TODO(zhangkelvin) Rewrite this in C++20 coroutine once that's available.
+ // TODO(177104308) Don't write all COPY ops up-front if merge sequence is
+ // written
auto converted = ConvertToCowOperations(partition_update_.operations(),
partition_update_.merge_operations());
@@ -114,14 +124,42 @@
TEST_AND_RETURN_FALSE_ERRNO(
source_fd->Open(install_part_.source_path.c_str(), O_RDONLY));
WriteAllCowOps(block_size_, converted, cow_writer_.get(), source_fd);
+ cow_writer_->AddLabel(0);
}
return true;
}
+bool VABCPartitionWriter::WriteMergeSequence(
+ const RepeatedPtrField<CowMergeOperation>& merge_sequence,
+ ICowWriter* cow_writer) {
+ std::vector<uint32_t> blocks_merge_order;
+ for (const auto& merge_op : merge_sequence) {
+ const auto& dst_extent = merge_op.dst_extent();
+ // In place copy are basically noops, they do not need to be "merged" at
+ // all, don't include them in merge sequence.
+ if (merge_op.type() == CowMergeOperation::COW_COPY &&
+ merge_op.src_extent() == merge_op.dst_extent()) {
+ continue;
+ }
+ // libsnapshot doesn't like us include REPLACE blocks in merge sequence,
+ // since we don't support XOR ops at this CL, skip them! Remove once we
+ // write XOR ops.
+ if (merge_op.type() == CowMergeOperation::COW_XOR) {
+ continue;
+ }
+ // libsnapshot prefers blocks in reverse order
+ for (int i = dst_extent.num_blocks() - 1; i >= 0; i--) {
+ blocks_merge_order.push_back(dst_extent.start_block() + i);
+ }
+ }
+ return cow_writer->AddSequenceData(blocks_merge_order.size(),
+ blocks_merge_order.data());
+}
+
bool VABCPartitionWriter::WriteAllCowOps(
size_t block_size,
const std::vector<CowOperation>& converted,
- android::snapshot::ICowWriter* cow_writer,
+ ICowWriter* cow_writer,
FileDescriptorPtr source_fd) {
std::vector<uint8_t> buffer(block_size);
diff --git a/payload_consumer/vabc_partition_writer.h b/payload_consumer/vabc_partition_writer.h
index e8601a9..c73bd4d 100644
--- a/payload_consumer/vabc_partition_writer.h
+++ b/payload_consumer/vabc_partition_writer.h
@@ -34,8 +34,7 @@
VABCPartitionWriter(const PartitionUpdate& partition_update,
const InstallPlan::Partition& install_part,
DynamicPartitionControlInterface* dynamic_control,
- size_t block_size,
- bool is_interactive);
+ size_t block_size);
[[nodiscard]] bool Init(const InstallPlan* install_plan,
bool source_may_exist,
size_t next_op_index) override;
@@ -72,11 +71,14 @@
[[nodiscard]] bool FinishedInstallOps() override;
int Close() override;
+ // Send merge sequence data to cow writer
+ static bool WriteMergeSequence(
+ const ::google::protobuf::RepeatedPtrField<CowMergeOperation>& merge_ops,
+ android::snapshot::ICowWriter* cow_writer);
private:
std::unique_ptr<android::snapshot::ISnapshotWriter> cow_writer_;
- bool OpenCurrentECCPartition();
[[nodiscard]] std::unique_ptr<ExtentWriter> CreateBaseExtentWriter();
const PartitionUpdate& partition_update_;
@@ -85,7 +87,6 @@
// Path to source partition
std::string source_path_;
- const bool interactive_;
const size_t block_size_;
InstallOperationExecutor executor_;
VerifiedSourceFd verified_source_fd_;