aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Zheng <zhengdaniel@google.com>2024-02-29 05:20:48 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2024-02-29 05:20:48 +0000
commit4b7655d03d895592748c477d4da7b25603cff0dc (patch)
tree6e1e23963a7c799d78a1ec56aa13b636adc2abf8
parentf9ad892e9fca24c56f21152cb35c0f341f2c041d (diff)
parent5a6e32b3b8f52541ee3ccd96158ea0ebfe4338e8 (diff)
downloadupdate_engine-4b7655d03d895592748c477d4da7b25603cff0dc.tar.gz
update_engine: factor out source_copy method am: 5a6e32b3b8
Original change: https://android-review.googlesource.com/c/platform/system/update_engine/+/2976857 Change-Id: I10daddd806fa9437ed1d53feb9feea8f98a073b0 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--payload_consumer/vabc_partition_writer.cc140
-rw-r--r--payload_consumer/vabc_partition_writer.h8
2 files changed, 86 insertions, 62 deletions
diff --git a/payload_consumer/vabc_partition_writer.cc b/payload_consumer/vabc_partition_writer.cc
index 97de934f..c879375d 100644
--- a/payload_consumer/vabc_partition_writer.cc
+++ b/payload_consumer/vabc_partition_writer.cc
@@ -97,6 +97,78 @@ VABCPartitionWriter::VABCPartitionWriter(
<< copy_blocks_.blocks() << " copy blocks";
}
+bool VABCPartitionWriter::ProcessSourceCopyOperation(
+ const InstallOperation& operation,
+ const size_t block_size,
+ const ExtentRanges& copy_blocks,
+ const FileDescriptorPtr& source_fd,
+ android::snapshot::ICowWriter* cow_writer,
+ bool sequence_op_supported) {
+ // COPY ops are already handled during Init(), no need to do actual work, but
+ // we still want to verify that all blocks contain expected data.
+ TEST_AND_RETURN_FALSE(source_fd != nullptr);
+ std::vector<CowOperation> converted;
+
+ const auto& src_extents = operation.src_extents();
+ const auto& dst_extents = operation.dst_extents();
+ BlockIterator it1{src_extents};
+ BlockIterator it2{dst_extents};
+ const bool userSnapshots = android::base::GetBoolProperty(
+ "ro.virtual_ab.userspace.snapshots.enabled", false);
+ // For devices not supporting XOR, sequence op is not supported, so all COPY
+ // operations are written up front in strict merge order.
+ while (!it1.is_end() && !it2.is_end()) {
+ const auto src_block = *it1;
+ const auto dst_block = *it2;
+ ++it1;
+ ++it2;
+ if (src_block == dst_block) {
+ continue;
+ }
+ if (copy_blocks.ContainsBlock(dst_block)) {
+ if (sequence_op_supported) {
+ push_back(&converted, {CowOperation::CowCopy, src_block, dst_block, 1});
+ }
+ } else {
+ push_back(&converted,
+ {CowOperation::CowReplace, src_block, dst_block, 1});
+ }
+ }
+ std::vector<uint8_t> buffer;
+ for (const auto& cow_op : converted) {
+ if (cow_op.op == CowOperation::CowCopy) {
+ if (userSnapshots) {
+ cow_writer->AddCopy(
+ cow_op.dst_block, cow_op.src_block, cow_op.block_count);
+ } else {
+ // Add blocks in reverse order, because snapused specifically prefers
+ // this ordering. Since we already eliminated all self-overlapping
+ // SOURCE_COPY during delta generation, this should be safe to do.
+ for (size_t i = cow_op.block_count; i > 0; i--) {
+ TEST_AND_RETURN_FALSE(cow_writer->AddCopy(cow_op.dst_block + i - 1,
+ cow_op.src_block + i - 1));
+ }
+ }
+ continue;
+ }
+ buffer.resize(block_size * cow_op.block_count);
+ ssize_t bytes_read = 0;
+ TEST_AND_RETURN_FALSE(utils::ReadAll(source_fd,
+ buffer.data(),
+ block_size * cow_op.block_count,
+ cow_op.src_block * block_size,
+ &bytes_read));
+ if (bytes_read <= 0 || static_cast<size_t>(bytes_read) != buffer.size()) {
+ LOG(ERROR) << "source_fd->Read failed: " << bytes_read
+ << "\ncow op: " << cow_op.op;
+ return false;
+ }
+ TEST_AND_RETURN_FALSE(cow_writer->AddRawBlocks(
+ cow_op.dst_block, buffer.data(), buffer.size()));
+ }
+ return true;
+}
+
bool VABCPartitionWriter::DoesDeviceSupportsXor() {
return dynamic_control_->GetVirtualAbCompressionXorFeatureFlag().IsEnabled();
}
@@ -272,70 +344,14 @@ std::unique_ptr<ExtentWriter> VABCPartitionWriter::CreateBaseExtentWriter() {
[[nodiscard]] bool VABCPartitionWriter::PerformSourceCopyOperation(
const InstallOperation& operation, ErrorCode* error) {
- // COPY ops are already handled during Init(), no need to do actual work, but
- // we still want to verify that all blocks contain expected data.
auto source_fd = verified_source_fd_.ChooseSourceFD(operation, error);
- TEST_AND_RETURN_FALSE(source_fd != nullptr);
- std::vector<CowOperation> converted;
- const auto& src_extents = operation.src_extents();
- const auto& dst_extents = operation.dst_extents();
- BlockIterator it1{src_extents};
- BlockIterator it2{dst_extents};
- const bool userSnapshots = android::base::GetBoolProperty(
- "ro.virtual_ab.userspace.snapshots.enabled", false);
- // For devices not supporting XOR, sequence op is not supported, so all COPY
- // operations are written up front in strict merge order.
- const auto sequence_op_supported = DoesDeviceSupportsXor();
- while (!it1.is_end() && !it2.is_end()) {
- const auto src_block = *it1;
- const auto dst_block = *it2;
- ++it1;
- ++it2;
- if (src_block == dst_block) {
- continue;
- }
- if (copy_blocks_.ContainsBlock(dst_block)) {
- if (sequence_op_supported) {
- push_back(&converted, {CowOperation::CowCopy, src_block, dst_block, 1});
- }
- } else {
- push_back(&converted,
- {CowOperation::CowReplace, src_block, dst_block, 1});
- }
- }
- std::vector<uint8_t> buffer;
- for (const auto& cow_op : converted) {
- if (cow_op.op == CowOperation::CowCopy) {
- if (userSnapshots) {
- cow_writer_->AddCopy(
- cow_op.dst_block, cow_op.src_block, cow_op.block_count);
- } else {
- // Add blocks in reverse order, because snapused specifically prefers
- // this ordering. Since we already eliminated all self-overlapping
- // SOURCE_COPY during delta generation, this should be safe to do.
- for (size_t i = cow_op.block_count; i > 0; i--) {
- TEST_AND_RETURN_FALSE(cow_writer_->AddCopy(cow_op.dst_block + i - 1,
- cow_op.src_block + i - 1));
- }
- }
- continue;
- }
- buffer.resize(block_size_ * cow_op.block_count);
- ssize_t bytes_read = 0;
- TEST_AND_RETURN_FALSE(utils::ReadAll(source_fd,
- buffer.data(),
- block_size_ * cow_op.block_count,
- cow_op.src_block * block_size_,
- &bytes_read));
- if (bytes_read <= 0 || static_cast<size_t>(bytes_read) != buffer.size()) {
- LOG(ERROR) << "source_fd->Read failed: " << bytes_read;
- return false;
- }
- TEST_AND_RETURN_FALSE(cow_writer_->AddRawBlocks(
- cow_op.dst_block, buffer.data(), buffer.size()));
- }
- return true;
+ return ProcessSourceCopyOperation(operation,
+ block_size_,
+ copy_blocks_,
+ source_fd,
+ cow_writer_.get(),
+ DoesDeviceSupportsXor());
}
bool VABCPartitionWriter::PerformReplaceOperation(const InstallOperation& op,
diff --git a/payload_consumer/vabc_partition_writer.h b/payload_consumer/vabc_partition_writer.h
index 977fbe5d..bd3db79e 100644
--- a/payload_consumer/vabc_partition_writer.h
+++ b/payload_consumer/vabc_partition_writer.h
@@ -34,6 +34,14 @@
namespace chromeos_update_engine {
class VABCPartitionWriter final : public PartitionWriterInterface {
public:
+ static bool ProcessSourceCopyOperation(
+ const InstallOperation& operation,
+ const size_t block_size,
+ const ExtentRanges& copy_blocks,
+ const FileDescriptorPtr& source_fd,
+ android::snapshot::ICowWriter* cow_writer,
+ bool sequence_op_supported);
+
VABCPartitionWriter(const PartitionUpdate& partition_update,
const InstallPlan::Partition& install_part,
DynamicPartitionControlInterface* dynamic_control,