Index: src/platform/update_engine/delta_diff_generator.cc |
diff --git a/src/platform/update_engine/delta_diff_generator.cc b/src/platform/update_engine/delta_diff_generator.cc |
index 6b880cd2d080503c2728c0c17f56fce804e96966..23c5fc8d8a3a1f975b2a289190c4d17a44be5746 100644 |
--- a/src/platform/update_engine/delta_diff_generator.cc |
+++ b/src/platform/update_engine/delta_diff_generator.cc |
@@ -390,6 +390,7 @@ bool WriteUint64AsBigEndian(FileWriter* writer, const uint64_t value) { |
void InstallOperationsToManifest( |
const Graph& graph, |
const vector<Vertex::Index>& order, |
+ const vector<DeltaArchiveManifest_InstallOperation>& kernel_ops, |
DeltaArchiveManifest* out_manifest) { |
for (vector<Vertex::Index>::const_iterator it = order.begin(); |
it != order.end(); ++it) { |
@@ -397,6 +398,12 @@ void InstallOperationsToManifest( |
out_manifest->add_install_operations(); |
*op = graph[*it].op; |
} |
+ for (vector<DeltaArchiveManifest_InstallOperation>::const_iterator it = |
+ kernel_ops.begin(); it != kernel_ops.end(); ++it) { |
+ DeltaArchiveManifest_InstallOperation* op = |
+ out_manifest->add_kernel_install_operations(); |
+ *op = *it; |
+ } |
} |
void CheckGraph(const Graph& graph) { |
@@ -405,6 +412,55 @@ void CheckGraph(const Graph& graph) { |
} |
} |
+// Delta compresses a kernel partition new_kernel_part with knowledge of |
+// the old kernel partition old_kernel_part. |
+bool DeltaCompressKernelPartition( |
+ const string& old_kernel_part, |
+ const string& new_kernel_part, |
+ vector<DeltaArchiveManifest_InstallOperation>* ops, |
+ int blobs_fd, |
+ off_t* blobs_length) { |
+ // For now, just bsdiff the kernel partition as a whole. |
+ // TODO(adlr): Use knowledge of how the kernel partition is laid out |
+ // to more efficiently compress it. |
+ |
+ LOG(INFO) << "Delta compressing kernel partition..."; |
+ |
+ // Add a new install operation |
+ ops->resize(1); |
+ DeltaArchiveManifest_InstallOperation* op = &(*ops)[0]; |
+ op->set_type(DeltaArchiveManifest_InstallOperation_Type_BSDIFF); |
+ op->set_data_offset(*blobs_length); |
+ |
+ // Do the actual compression |
+ vector<char> data; |
+ TEST_AND_RETURN_FALSE(BsdiffFiles(old_kernel_part, new_kernel_part, &data)); |
+ TEST_AND_RETURN_FALSE(utils::WriteAll(blobs_fd, &data[0], data.size())); |
+ *blobs_length += data.size(); |
+ |
+ off_t old_part_size = utils::FileSize(old_kernel_part); |
+ TEST_AND_RETURN_FALSE(old_part_size >= 0); |
+ off_t new_part_size = utils::FileSize(new_kernel_part); |
+ TEST_AND_RETURN_FALSE(new_part_size >= 0); |
+ |
+ op->set_data_length(data.size()); |
+ |
+ op->set_src_length(old_part_size); |
+ op->set_dst_length(new_part_size); |
+ |
+ // Theres a single src/dest extent for each |
+ Extent* src_extent = op->add_src_extents(); |
+ src_extent->set_start_block(0); |
+ src_extent->set_num_blocks((old_part_size + kBlockSize - 1) / kBlockSize); |
+ |
+ Extent* dst_extent = op->add_dst_extents(); |
+ dst_extent->set_start_block(0); |
+ dst_extent->set_num_blocks((new_part_size + kBlockSize - 1) / kBlockSize); |
+ |
+ LOG(INFO) << "Done delta compressing kernel partition."; |
+ return true; |
+} |
+ |
} // namespace {} |
bool DeltaDiffGenerator::ReadFileToDiff( |
@@ -653,9 +709,15 @@ bool DeltaDiffGenerator::ReorderDataBlobs( |
ScopedFileWriterCloser writer_closer(&writer); |
uint64_t out_file_size = 0; |
- for (int i = 0; i < manifest->install_operations_size(); i++) { |
- DeltaArchiveManifest_InstallOperation* op = |
- manifest->mutable_install_operations(i); |
+ for (int i = 0; i < (manifest->install_operations_size() + |
+ manifest->kernel_install_operations_size()); i++) { |
+ DeltaArchiveManifest_InstallOperation* op = NULL; |
+ if (i < manifest->install_operations_size()) { |
+ op = manifest->mutable_install_operations(i); |
+ } else { |
+ op = manifest->mutable_kernel_install_operations( |
+ i - manifest->install_operations_size()); |
+ } |
if (!op->has_data_offset()) |
continue; |
CHECK(op->has_data_length()); |
@@ -671,11 +733,14 @@ bool DeltaDiffGenerator::ReorderDataBlobs( |
return true; |
} |
-bool DeltaDiffGenerator::GenerateDeltaUpdateFile(const string& old_root, |
- const string& old_image, |
- const string& new_root, |
- const string& new_image, |
- const string& output_path) { |
+bool DeltaDiffGenerator::GenerateDeltaUpdateFile( |
+ const string& old_root, |
+ const string& old_image, |
+ const string& new_root, |
+ const string& new_image, |
+ const std::string& old_kernel_part, |
+ const std::string& new_kernel_part, |
+ const string& output_path) { |
struct stat old_image_stbuf; |
TEST_AND_RETURN_FALSE_ERRNO(stat(old_image.c_str(), &old_image_stbuf) == 0); |
struct stat new_image_stbuf; |
@@ -687,6 +752,10 @@ bool DeltaDiffGenerator::GenerateDeltaUpdateFile(const string& old_root, |
LOG_IF(FATAL, old_image_stbuf.st_size % kBlockSize) |
<< "Old image not a multiple of block size " << kBlockSize; |
+ // Sanity check kernel partition args |
+ TEST_AND_RETURN_FALSE(utils::FileSize(old_kernel_part) >= 0); |
+ TEST_AND_RETURN_FALSE(utils::FileSize(new_kernel_part) >= 0); |
+ |
vector<Block> blocks(min(old_image_stbuf.st_size / kBlockSize, |
new_image_stbuf.st_size / kBlockSize)); |
LOG(INFO) << "invalid: " << Vertex::kInvalidIndex; |
@@ -704,6 +773,8 @@ bool DeltaDiffGenerator::GenerateDeltaUpdateFile(const string& old_root, |
LOG(INFO) << "Reading files..."; |
+ vector<DeltaArchiveManifest_InstallOperation> kernel_ops; |
+ |
DeltaArchiveManifest_InstallOperation final_op; |
{ |
int fd; |
@@ -720,12 +791,18 @@ bool DeltaDiffGenerator::GenerateDeltaUpdateFile(const string& old_root, |
&data_file_size)); |
CheckGraph(graph); |
- // TODO(adlr): read all the rest of the blocks in |
TEST_AND_RETURN_FALSE(ReadUnwrittenBlocks(blocks, |
fd, |
&data_file_size, |
new_image, |
&final_op)); |
+ |
+ // Read kernel partition |
+ TEST_AND_RETURN_FALSE(DeltaCompressKernelPartition(old_kernel_part, |
+ new_kernel_part, |
+ &kernel_ops, |
+ fd, |
+ &data_file_size)); |
} |
CheckGraph(graph); |
@@ -753,7 +830,7 @@ bool DeltaDiffGenerator::GenerateDeltaUpdateFile(const string& old_root, |
// Convert to protobuf Manifest object |
DeltaArchiveManifest manifest; |
CheckGraph(graph); |
- InstallOperationsToManifest(graph, final_order, &manifest); |
+ InstallOperationsToManifest(graph, final_order, kernel_ops, &manifest); |
{ |
// Write final operation |
DeltaArchiveManifest_InstallOperation* op = |
@@ -762,9 +839,9 @@ bool DeltaDiffGenerator::GenerateDeltaUpdateFile(const string& old_root, |
CHECK(op->has_type()); |
LOG(INFO) << "final op length: " << op->data_length(); |
} |
+ |
CheckGraph(graph); |
manifest.set_block_size(kBlockSize); |
- // TODO(adlr): set checksums |
// Reorder the data blobs with the newly ordered manifest |
string ordered_blobs_path; |
@@ -780,9 +857,13 @@ bool DeltaDiffGenerator::GenerateDeltaUpdateFile(const string& old_root, |
{ |
vector<uint32_t> written_count(blocks.size(), 0); |
uint64_t next_blob_offset = 0; |
- for (int i = 0; i < manifest.install_operations_size(); i++) { |
+ for (int i = 0; i < (manifest.install_operations_size() + |
+ manifest.kernel_install_operations_size()); i++) { |
const DeltaArchiveManifest_InstallOperation& op = |
- manifest.install_operations(i); |
+ i < manifest.install_operations_size() ? |
+ manifest.install_operations(i) : |
+ manifest.kernel_install_operations( |
+ i - manifest.install_operations_size()); |
for (int j = 0; j < op.dst_extents_size(); j++) { |
const Extent& extent = op.dst_extents(j); |
for (uint64_t block = extent.start_block(); |