AU: do not copy filesystem during full updates
The filesystem copying stage is redundant during full updates, where the
partition is being entirely overwritten regardless of its previous
content. It is also a very wasteful step, causing intensive I/O and
kernel buffer pressure, and known to (sometimes) cause jank and
otherwise have detrimental effects on our user experience.
This CL eliminates filesystem copying for full updates:
1) The decision is based on whether the Omaha response indicates that
this is a full update.
2) To be safe, we also ensure that the payload manifest does not contain
old partition hashes, which is indicative of a delta update.
Note that it is generally desirable to base the decision solely on #2
above (and ignore #1 altogether). However, this will require more
extensive re-engineering of the update flow, as filesystem copying
currently happens prior to the manifest being downloaded.
BUG=chromium:189855
TEST=Full and delta updates run correctly on x86-alex
Change-Id: Ic0dc6e32913cfb96019606624ec6b87c2e5b3ebb
Reviewed-on: https://gerrit.chromium.org/gerrit/43665
Commit-Queue: Gilad Arnold <garnold@chromium.org>
Reviewed-by: Gilad Arnold <garnold@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
diff --git a/delta_performer.cc b/delta_performer.cc
index 360272f..5615801 100644
--- a/delta_performer.cc
+++ b/delta_performer.cc
@@ -383,6 +383,11 @@
if (result == kMetadataParseInsufficientData) {
return true;
}
+
+ // Checks the integrity of the payload manifest.
+ if ((*error = ValidateManifest()) != kErrorCodeSuccess)
+ return false;
+
// Remove protobuf and header info from buffer_, so buffer_ contains
// just data blobs
DiscardBufferHeadBytes(manifest_metadata_size_);
@@ -831,6 +836,30 @@
return kErrorCodeSuccess;
}
+ErrorCode DeltaPerformer::ValidateManifest() {
+ // Ensure that a full update does not contain old partition hashes, which is
+ // indicative of a delta.
+ //
+ // TODO(garnold) in general, the presence of an old partition hash should be
+ // the sole indicator for a delta update, as we would generally like update
+ // payloads to be self contained and not assume an Omaha response to tell us
+ // that. However, since this requires some massive reengineering of the update
+ // flow (making filesystem copying happen conditionally only *after*
+ // downloading and parsing of the update manifest) we'll put it off for now.
+ // See chromium-os:7597 for further discussion.
+ if (install_plan_->is_full_update &&
+ (manifest_.has_old_kernel_info() || manifest_.has_old_rootfs_info())) {
+ LOG(ERROR) << "Purported full payload contains old partition "
+ "hash(es), aborting update";
+ return kErrorCodePayloadMismatchedType;
+ }
+
+ // TODO(garnold) we should be adding more and more manifest checks, such as
+ // partition boundaries etc (see chromium-os:37661).
+
+ return kErrorCodeSuccess;
+}
+
ErrorCode DeltaPerformer::ValidateOperationHash(
const DeltaArchiveManifest_InstallOperation& operation) {