OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "update_engine/delta_diff_generator.h" | 5 #include "update_engine/delta_diff_generator.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <inttypes.h> | 9 #include <inttypes.h> |
10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
11 #include <sys/types.h> | 11 #include <sys/types.h> |
12 | 12 |
13 #include <base/logging.h> | |
petkov
2010/12/10 00:46:55
move this block of includes after the c++ headers
thieule
2010/12/14 23:11:21
Done.
| |
14 #include <base/string_util.h> | |
15 #include <bzlib.h> | |
16 | |
petkov
2010/12/10 00:46:55
no need for blank line
thieule
2010/12/14 23:11:21
Done.
| |
17 #include <ext2fs/ext2_io.h> | |
18 #include <ext2fs/ext2fs.h> | |
19 | |
13 #include <algorithm> | 20 #include <algorithm> |
14 #include <map> | 21 #include <map> |
15 #include <set> | 22 #include <set> |
16 #include <string> | 23 #include <string> |
17 #include <utility> | 24 #include <utility> |
18 #include <vector> | 25 #include <vector> |
19 | 26 |
20 #include <base/logging.h> | |
21 #include <base/string_util.h> | |
22 #include <bzlib.h> | |
23 | |
24 #include "update_engine/bzip.h" | 27 #include "update_engine/bzip.h" |
25 #include "update_engine/cycle_breaker.h" | 28 #include "update_engine/cycle_breaker.h" |
26 #include "update_engine/extent_mapper.h" | 29 #include "update_engine/extent_mapper.h" |
27 #include "update_engine/extent_ranges.h" | 30 #include "update_engine/extent_ranges.h" |
28 #include "update_engine/file_writer.h" | 31 #include "update_engine/file_writer.h" |
29 #include "update_engine/filesystem_iterator.h" | 32 #include "update_engine/filesystem_iterator.h" |
30 #include "update_engine/full_update_generator.h" | 33 #include "update_engine/full_update_generator.h" |
31 #include "update_engine/graph_types.h" | 34 #include "update_engine/graph_types.h" |
32 #include "update_engine/graph_utils.h" | 35 #include "update_engine/graph_utils.h" |
33 #include "update_engine/omaha_hash_calculator.h" | 36 #include "update_engine/omaha_hash_calculator.h" |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 blocks, | 237 blocks, |
235 old_root, | 238 old_root, |
236 new_root, | 239 new_root, |
237 fs_iter.GetPartialPath(), | 240 fs_iter.GetPartialPath(), |
238 data_fd, | 241 data_fd, |
239 data_file_size)); | 242 data_file_size)); |
240 } | 243 } |
241 return true; | 244 return true; |
242 } | 245 } |
243 | 246 |
247 // Read data from the specified extents. | |
248 bool ReadExtentsData(const ext2_filsys fs, | |
249 const vector<Extent>& extents, | |
250 vector<char>* data) { | |
251 // Resize the data buffer to hold all data in the extents | |
252 size_t num_data_blocks = 0; | |
253 for (vector<Extent>::const_iterator it = extents.begin(); | |
254 it != extents.end(); it++) { | |
255 num_data_blocks += it->num_blocks(); | |
256 } | |
257 | |
258 data->resize(num_data_blocks * kBlockSize); | |
259 | |
260 // Read in the data blocks | |
261 const size_t max_read_blocks = 256; | |
262 vector<Block>::size_type blocks_copied_count = 0; | |
263 for (vector<Extent>::const_iterator it = extents.begin(); | |
264 it != extents.end(); it++) { | |
265 vector<Block>::size_type blocks_read = 0; | |
266 while (blocks_read < it->num_blocks()) { | |
267 const int copy_block_cnt = | |
268 min(max_read_blocks, | |
269 static_cast<vector<char>::size_type>( | |
270 it->num_blocks() - blocks_read)); | |
271 TEST_AND_RETURN_FALSE_ERRCODE( | |
272 io_channel_read_blk(fs->io, | |
273 it->start_block() + blocks_read, | |
274 copy_block_cnt, | |
275 &(*data)[blocks_copied_count * kBlockSize])); | |
276 blocks_read += copy_block_cnt; | |
277 blocks_copied_count += copy_block_cnt; | |
278 } | |
279 } | |
280 | |
281 return true; | |
282 } | |
283 | |
284 // Compute the bsdiff between two metadata blobs. | |
285 bool ComputeMetadataBsdiff(const vector<char>& old_metadata, | |
286 const vector<char>& new_metadata, | |
287 vector<char>* bsdiff_delta) { | |
288 const string kTempFileTemplate("/tmp/CrAU_temp_data.XXXXXX"); | |
289 | |
290 // Write the metadata buffers to temporary files | |
291 int old_fd; | |
292 string temp_old_file_path; | |
293 TEST_AND_RETURN_FALSE( | |
294 utils::MakeTempFile(kTempFileTemplate, &temp_old_file_path, &old_fd)); | |
295 TEST_AND_RETURN_FALSE(old_fd >= 0); | |
296 ScopedPathUnlinker temp_old_file_path_unlinker(temp_old_file_path); | |
297 ScopedFdCloser old_fd_closer(&old_fd); | |
298 TEST_AND_RETURN_FALSE(utils::WriteAll(old_fd, | |
299 &old_metadata[0], | |
300 old_metadata.size())); | |
301 | |
302 int new_fd; | |
303 string temp_new_file_path; | |
304 TEST_AND_RETURN_FALSE( | |
305 utils::MakeTempFile(kTempFileTemplate, &temp_new_file_path, &new_fd)); | |
306 TEST_AND_RETURN_FALSE(new_fd >= 0); | |
307 ScopedPathUnlinker temp_new_file_path_unlinker(temp_new_file_path); | |
308 ScopedFdCloser new_fd_closer(&new_fd); | |
309 TEST_AND_RETURN_FALSE(utils::WriteAll(new_fd, | |
310 &new_metadata[0], | |
311 new_metadata.size())); | |
312 | |
313 // Perform bsdiff on these files | |
314 TEST_AND_RETURN_FALSE( | |
315 BsdiffFiles(temp_old_file_path, temp_new_file_path, bsdiff_delta)); | |
316 CHECK_GT(bsdiff_delta->size(), 0); | |
317 | |
318 return true; | |
319 } | |
320 | |
321 // Add the specified metadata extents to the graph and blocks vector. | |
322 bool AddMetadataExtents(Graph* graph, | |
323 vector<Block>* blocks, | |
324 const ext2_filsys fs_old, | |
325 const ext2_filsys fs_new, | |
326 const string& metadata_name, | |
327 const vector<Extent>& extents, | |
328 int data_fd, | |
329 off_t* data_file_size) { | |
330 vector<char> data; // Data blob that will be written to delta file. | |
331 | |
332 // Read in the metadata blocks from the old and new image. | |
333 vector<char> old_data; | |
334 TEST_AND_RETURN_FALSE(ReadExtentsData(fs_old, extents, &old_data)); | |
335 | |
336 vector<char> new_data; | |
337 TEST_AND_RETURN_FALSE(ReadExtentsData(fs_new, extents, &new_data)); | |
338 | |
339 // Determine the best way to compress this. | |
340 vector<char> new_data_bz; | |
341 TEST_AND_RETURN_FALSE(BzipCompress(new_data, &new_data_bz)); | |
342 CHECK(!new_data_bz.empty()); | |
343 | |
344 DeltaArchiveManifest_InstallOperation op; | |
345 size_t current_best_size = 0; | |
346 if (new_data.size() <= new_data_bz.size()) { | |
347 op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE); | |
348 current_best_size = new_data.size(); | |
349 data = new_data; | |
350 } else { | |
351 op.set_type(DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ); | |
352 current_best_size = new_data_bz.size(); | |
353 data = new_data_bz; | |
354 } | |
355 | |
356 if (old_data == new_data) { | |
357 // No change in data. | |
358 op.set_type(DeltaArchiveManifest_InstallOperation_Type_MOVE); | |
359 current_best_size = 0; | |
360 data.clear(); | |
361 } else { | |
362 // Try bsdiff of old to new data | |
363 vector<char> bsdiff_delta; | |
364 TEST_AND_RETURN_FALSE(ComputeMetadataBsdiff(old_data, | |
365 new_data, | |
366 &bsdiff_delta)); | |
367 CHECK_GT(bsdiff_delta.size(), 0); | |
368 | |
369 if (bsdiff_delta.size() < current_best_size) { | |
370 op.set_type(DeltaArchiveManifest_InstallOperation_Type_BSDIFF); | |
371 current_best_size = bsdiff_delta.size(); | |
372 data = bsdiff_delta; | |
373 } | |
374 } | |
375 | |
376 CHECK_EQ(data.size(), current_best_size); | |
377 | |
378 // Set the source and dest extents to be the same since the filesystem | |
379 // structures are identical | |
380 if (op.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE || | |
381 op.type() == DeltaArchiveManifest_InstallOperation_Type_BSDIFF) { | |
382 DeltaDiffGenerator::StoreExtents(extents, op.mutable_src_extents()); | |
383 op.set_src_length(old_data.size()); | |
384 } | |
385 | |
386 DeltaDiffGenerator::StoreExtents(extents, op.mutable_dst_extents()); | |
387 op.set_dst_length(new_data.size()); | |
388 | |
389 // Write data to output file | |
390 if (op.type() != DeltaArchiveManifest_InstallOperation_Type_MOVE) { | |
391 op.set_data_offset(*data_file_size); | |
392 op.set_data_length(data.size()); | |
393 } | |
394 | |
395 TEST_AND_RETURN_FALSE(utils::WriteAll(data_fd, &data[0], data.size())); | |
396 *data_file_size += data.size(); | |
397 | |
398 // Now, insert into graph and blocks vector | |
399 graph->resize(graph->size() + 1); | |
400 Vertex::Index vertex = graph->size() - 1; | |
401 (*graph)[vertex].op = op; | |
402 CHECK((*graph)[vertex].op.has_type()); | |
403 (*graph)[vertex].file_name = metadata_name; | |
404 | |
405 TEST_AND_RETURN_FALSE(AddInstallOpToBlocksVector((*graph)[vertex].op, | |
406 blocks, | |
407 *graph, | |
408 vertex)); | |
409 | |
410 return true; | |
411 } | |
412 | |
413 // Reads the file system metadata extents. | |
414 bool ReadFilesystemMetadata(Graph* graph, | |
415 vector<Block>* blocks, | |
416 const ext2_filsys fs_old, | |
417 const ext2_filsys fs_new, | |
418 int data_fd, | |
419 off_t* data_file_size) { | |
420 LOG(INFO) << "Processing <rootfs-metadata>"; | |
421 | |
422 // Read all the extents that belong to the main file system metadata. | |
423 // The metadata blocks are at the the start of each block group and goes | |
petkov
2010/12/10 00:46:55
typo: the the
thieule
2010/12/14 23:11:21
Done.
| |
424 // until the end of the inode table. | |
425 for (dgrp_t bg = 0; bg < fs_old->group_desc_count; bg++) { | |
426 struct ext2_group_desc* group_desc = &fs_old->group_desc[bg]; | |
427 __u32 num_metadata_blocks = (group_desc->bg_inode_table + | |
428 fs_old->inode_blocks_per_group) - | |
429 (bg * fs_old->super->s_blocks_per_group); | |
430 __u32 bg_start_block = bg * fs_old->super->s_blocks_per_group; | |
431 | |
432 // Due to bsdiff slowness, we're going to break each block group down | |
petkov
2010/12/10 00:46:55
would it be better for the payload size to not bre
thieule
2010/12/14 23:11:21
I ran this without breaking up into chunks and bsd
| |
433 // into metadata chunks and feed them to bsdiff. | |
434 __u32 num_chunks = 4; | |
435 __u32 blocks_per_chunk = num_metadata_blocks / num_chunks; | |
436 __u32 curr_block = bg_start_block; | |
437 for (__u32 chunk = 0; chunk < num_chunks; chunk++) { | |
438 | |
petkov
2010/12/10 00:46:55
remove blank line
thieule
2010/12/14 23:11:21
Done.
| |
439 __u32 end_block = 0; | |
440 if (chunk < num_chunks - 1) { | |
441 end_block = curr_block + blocks_per_chunk; | |
442 } else { | |
443 end_block = bg_start_block + num_metadata_blocks; | |
444 } | |
445 | |
446 vector<Extent> extents; | |
447 for (__u32 i = curr_block; i < end_block; i++) { | |
petkov
2010/12/10 00:46:55
there's an ExtentForRange utility in extent_ranges
thieule
2010/12/14 23:11:21
Done.
| |
448 graph_utils::AppendBlockToExtents(&extents, i); | |
449 } | |
450 | |
451 std::stringstream metadata_name; | |
452 metadata_name << "<rootfs-bg-" << bg << "-" << chunk << "-metadata>"; | |
petkov
2010/12/10 00:46:55
maybe use StringPrintf instead?
thieule
2010/12/14 23:11:21
Done.
| |
453 | |
454 LOG(INFO) << "Processing " << metadata_name.str(); | |
455 | |
456 TEST_AND_RETURN_FALSE(AddMetadataExtents(graph, | |
457 blocks, | |
458 fs_old, | |
459 fs_new, | |
460 metadata_name.str(), | |
461 extents, | |
462 data_fd, | |
463 data_file_size)); | |
464 | |
465 curr_block += blocks_per_chunk; | |
466 } | |
467 } | |
468 | |
469 return true; | |
470 } | |
471 | |
472 // Processes all blocks belonging to an inode | |
473 int ProcessInodeAllBlocks(ext2_filsys fs, | |
474 blk_t* blocknr, | |
475 e2_blkcnt_t blockcnt, | |
476 blk_t ref_blk, | |
477 int ref_offset, | |
478 void* priv) { | |
479 vector<Extent>* extents = static_cast<vector<Extent>*>(priv); | |
480 graph_utils::AppendBlockToExtents(extents, *blocknr); | |
481 return 0; | |
482 } | |
483 | |
484 // Processes only indirect, double indirect or triple indirect metadata | |
485 // blocks belonging to an inode | |
486 int ProcessInodeMetadataBlocks(ext2_filsys fs, | |
487 blk_t* blocknr, | |
488 e2_blkcnt_t blockcnt, | |
489 blk_t ref_blk, | |
490 int ref_offset, | |
491 void* priv) { | |
492 vector<Extent>* extents = static_cast<vector<Extent>*>(priv); | |
493 if (blockcnt < 0) { | |
494 graph_utils::AppendBlockToExtents(extents, *blocknr); | |
495 } | |
496 return 0; | |
497 } | |
498 | |
499 // Read inode metadata blocks. | |
500 bool ReadInodeMetadata(Graph* graph, | |
501 vector<Block>* blocks, | |
502 const ext2_filsys fs_old, | |
503 const ext2_filsys fs_new, | |
504 int data_fd, | |
505 off_t* data_file_size) { | |
506 TEST_AND_RETURN_FALSE_ERRCODE(ext2fs_read_inode_bitmap(fs_old)); | |
507 | |
508 TEST_AND_RETURN_FALSE_ERRCODE(ext2fs_read_inode_bitmap(fs_new)); | |
509 | |
510 ext2_inode_scan iscan; | |
511 TEST_AND_RETURN_FALSE_ERRCODE(ext2fs_open_inode_scan(fs_old, 0, &iscan)); | |
512 | |
513 ext2_ino_t ino; | |
514 ext2_inode old_inode; | |
515 while (true) { | |
516 // Get the next inode on both file systems | |
517 errcode_t error = ext2fs_get_next_inode(iscan, &ino, &old_inode); | |
518 if (error) { | |
519 LOG(ERROR) << "Failed to retrieve next inode (" << error << ")"; | |
520 break; | |
521 } | |
522 | |
523 if (ino == 0) { | |
524 break; | |
525 } | |
526 | |
527 if (ino == EXT2_RESIZE_INO) { | |
528 continue; | |
529 } | |
530 | |
531 ext2_inode new_inode; | |
532 error = ext2fs_read_inode(fs_new, ino, &new_inode); | |
533 if (error) { | |
534 LOG(ERROR) << "Failed to retrieve new inode (" << error << ")"; | |
535 continue; | |
536 } | |
537 | |
538 // Skip inodes that are not in use | |
539 if (!ext2fs_test_inode_bitmap(fs_old->inode_map, ino) || | |
540 !ext2fs_test_inode_bitmap(fs_new->inode_map, ino)) { | |
541 continue; | |
542 } | |
543 | |
544 // Skip inodes that have no data blocks | |
545 if (old_inode.i_blocks == 0 || new_inode.i_blocks == 0) { | |
546 continue; | |
547 } | |
548 | |
549 // Skip inodes that are not the same type | |
550 bool is_old_dir = (ext2fs_check_directory(fs_old, ino) == 0); | |
551 bool is_new_dir = (ext2fs_check_directory(fs_new, ino) == 0); | |
552 if (is_old_dir != is_new_dir) { | |
553 continue; | |
554 } | |
555 | |
556 // Process the inodes metadata blocks | |
557 // For normal files, metadata blocks are indirect, double indirect | |
558 // and triple indirect blocks (no data blocks). For directories and | |
559 // the journal, all blocks are considered metadata blocks. | |
560 LOG(INFO) << "Processing inode " << ino << " metadata"; | |
561 | |
562 bool all_blocks = ((ino == EXT2_JOURNAL_INO) || is_old_dir || is_new_dir); | |
563 | |
564 vector<Extent> old_extents; | |
565 error = ext2fs_block_iterate2(fs_old, ino, 0, NULL, | |
566 all_blocks ? ProcessInodeAllBlocks : | |
567 ProcessInodeMetadataBlocks, | |
568 &old_extents); | |
569 if (error) { | |
570 LOG(ERROR) << "Failed to enumerate old inode " << ino | |
571 << " blocks (" << error << ")"; | |
572 continue; | |
573 } | |
574 | |
575 vector<Extent> new_extents; | |
576 error = ext2fs_block_iterate2(fs_new, ino, 0, NULL, | |
577 all_blocks ? ProcessInodeAllBlocks : | |
578 ProcessInodeMetadataBlocks, | |
579 &new_extents); | |
580 if (error) { | |
581 LOG(ERROR) << "Failed to enumerate new inode " << ino | |
582 << " blocks (" << error << ")"; | |
583 continue; | |
584 } | |
585 | |
586 // Skip inode if there are no metadata blocks | |
587 if (old_extents.size() == 0 || new_extents.size() == 0) { | |
588 continue; | |
589 } | |
590 | |
591 // Make sure the two inodes have the same metadata blocks | |
592 if (old_extents.size() != new_extents.size()) { | |
593 continue; | |
594 } | |
595 | |
596 bool same_metadata_extents = true; | |
597 vector<Extent>::iterator it_old; | |
598 vector<Extent>::iterator it_new; | |
599 for (it_old = old_extents.begin(), | |
600 it_new = new_extents.begin(); | |
601 it_old != old_extents.end() && it_new != new_extents.end(); | |
602 it_old++, it_new++) { | |
603 if (it_old->start_block() != it_new->start_block() || | |
604 it_old->num_blocks() != it_new->num_blocks()) { | |
605 same_metadata_extents = false; | |
606 break; | |
607 } | |
608 } | |
609 | |
610 if (!same_metadata_extents) { | |
611 continue; | |
612 } | |
613 | |
614 // We have identical inode metadata blocks, we can now add them to | |
615 // our graph and blocks vector | |
616 std::stringstream metadata_name; | |
617 metadata_name << "<rootfs-inode-" << ino << "-metadata>"; | |
618 TEST_AND_RETURN_FALSE(AddMetadataExtents(graph, | |
619 blocks, | |
620 fs_old, | |
621 fs_new, | |
622 metadata_name.str(), | |
623 old_extents, | |
624 data_fd, | |
625 data_file_size)); | |
626 } | |
627 | |
628 ext2fs_close_inode_scan(iscan); | |
629 | |
630 return true; | |
631 } | |
632 | |
244 // This class allocates non-existent temp blocks, starting from | 633 // This class allocates non-existent temp blocks, starting from |
245 // kTempBlockStart. Other code is responsible for converting these | 634 // kTempBlockStart. Other code is responsible for converting these |
246 // temp blocks into real blocks, as the client can't read or write to | 635 // temp blocks into real blocks, as the client can't read or write to |
247 // these blocks. | 636 // these blocks. |
248 class DummyExtentAllocator { | 637 class DummyExtentAllocator { |
249 public: | 638 public: |
250 explicit DummyExtentAllocator() | 639 explicit DummyExtentAllocator() |
251 : next_block_(kTempBlockStart) {} | 640 : next_block_(kTempBlockStart) {} |
252 vector<Extent> Allocate(const uint64_t block_count) { | 641 vector<Extent> Allocate(const uint64_t block_count) { |
253 vector<Extent> ret(1); | 642 vector<Extent> ret(1); |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
613 dst_extent->set_num_blocks((new_data.size() + kBlockSize - 1) / kBlockSize); | 1002 dst_extent->set_num_blocks((new_data.size() + kBlockSize - 1) / kBlockSize); |
614 } | 1003 } |
615 operation.set_dst_length(new_data.size()); | 1004 operation.set_dst_length(new_data.size()); |
616 | 1005 |
617 out_data->swap(data); | 1006 out_data->swap(data); |
618 *out_op = operation; | 1007 *out_op = operation; |
619 | 1008 |
620 return true; | 1009 return true; |
621 } | 1010 } |
622 | 1011 |
1012 bool DeltaDiffGenerator::DeltaReadMetadata(Graph* graph, | |
1013 vector<Block>* blocks, | |
1014 const string& old_image, | |
1015 const string& new_image, | |
1016 int data_fd, | |
1017 off_t* data_file_size) { | |
1018 // Open the two file systems. | |
1019 ext2_filsys fs_old; | |
1020 TEST_AND_RETURN_FALSE_ERRCODE(ext2fs_open(old_image.c_str(), 0, 0, 0, | |
1021 unix_io_manager, &fs_old)); | |
1022 ScopedExt2fsCloser fs_old_closer(fs_old); | |
1023 | |
1024 ext2_filsys fs_new; | |
1025 TEST_AND_RETURN_FALSE_ERRCODE(ext2fs_open(new_image.c_str(), 0, 0, 0, | |
1026 unix_io_manager, &fs_new)); | |
1027 ScopedExt2fsCloser fs_new_closer(fs_new); | |
1028 | |
1029 // Make sure these two file systems are the same. | |
petkov
2010/12/10 00:46:55
clarify that if they aren't the same we'll just se
thieule
2010/12/14 23:11:21
Done.
| |
1030 if (fs_old->blocksize != fs_new->blocksize || | |
1031 fs_old->fragsize != fs_new->fragsize || | |
1032 fs_old->group_desc_count != fs_new->group_desc_count || | |
1033 fs_old->inode_blocks_per_group != fs_new->inode_blocks_per_group || | |
1034 fs_old->super->s_inodes_count != fs_new->super->s_inodes_count || | |
1035 fs_old->super->s_blocks_count != fs_new->super->s_blocks_count) { | |
1036 return true; | |
1037 } | |
1038 | |
1039 // Process the main file system metadata (superblock, inode tables, etc) | |
1040 TEST_AND_RETURN_FALSE(ReadFilesystemMetadata(graph, | |
1041 blocks, | |
1042 fs_old, | |
1043 fs_new, | |
1044 data_fd, | |
1045 data_file_size)); | |
1046 | |
1047 // Process each inode metadata blocks. | |
1048 TEST_AND_RETURN_FALSE(ReadInodeMetadata(graph, | |
1049 blocks, | |
1050 fs_old, | |
1051 fs_new, | |
1052 data_fd, | |
1053 data_file_size)); | |
1054 | |
1055 return true; | |
1056 } | |
1057 | |
623 bool DeltaDiffGenerator::InitializePartitionInfo(bool is_kernel, | 1058 bool DeltaDiffGenerator::InitializePartitionInfo(bool is_kernel, |
624 const string& partition, | 1059 const string& partition, |
625 PartitionInfo* info) { | 1060 PartitionInfo* info) { |
626 int64_t size = 0; | 1061 int64_t size = 0; |
627 if (is_kernel) { | 1062 if (is_kernel) { |
628 size = utils::FileSize(partition); | 1063 size = utils::FileSize(partition); |
629 } else { | 1064 } else { |
630 int block_count = 0, block_size = 0; | 1065 int block_count = 0, block_size = 0; |
631 TEST_AND_RETURN_FALSE(utils::GetFilesystemSize(partition, | 1066 TEST_AND_RETURN_FALSE(utils::GetFilesystemSize(partition, |
632 &block_count, | 1067 &block_count, |
(...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1383 | 1818 |
1384 TEST_AND_RETURN_FALSE(DeltaReadFiles(&graph, | 1819 TEST_AND_RETURN_FALSE(DeltaReadFiles(&graph, |
1385 &blocks, | 1820 &blocks, |
1386 old_root, | 1821 old_root, |
1387 new_root, | 1822 new_root, |
1388 fd, | 1823 fd, |
1389 &data_file_size)); | 1824 &data_file_size)); |
1390 LOG(INFO) << "done reading normal files"; | 1825 LOG(INFO) << "done reading normal files"; |
1391 CheckGraph(graph); | 1826 CheckGraph(graph); |
1392 | 1827 |
1828 LOG(INFO) << "Starting metadata processing"; | |
1829 TEST_AND_RETURN_FALSE(DeltaReadMetadata(&graph, | |
1830 &blocks, | |
1831 old_image, | |
1832 new_image, | |
1833 fd, | |
1834 &data_file_size)); | |
1835 LOG(INFO) << "Done metadata processing"; | |
1836 CheckGraph(graph); | |
1837 | |
1393 graph.resize(graph.size() + 1); | 1838 graph.resize(graph.size() + 1); |
1394 TEST_AND_RETURN_FALSE(ReadUnwrittenBlocks(blocks, | 1839 TEST_AND_RETURN_FALSE(ReadUnwrittenBlocks(blocks, |
1395 fd, | 1840 fd, |
1396 &data_file_size, | 1841 &data_file_size, |
1397 new_image, | 1842 new_image, |
1398 &graph.back())); | 1843 &graph.back())); |
1399 | 1844 |
1400 // Final scratch block (if there's space) | 1845 // Final scratch block (if there's space) |
1401 if (blocks.size() < (kRootFSPartitionSize / kBlockSize)) { | 1846 if (blocks.size() < (kRootFSPartitionSize / kBlockSize)) { |
1402 scratch_vertex = graph.size(); | 1847 scratch_vertex = graph.size(); |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1583 | 2028 |
1584 LOG(INFO) << "All done. Successfully created delta file."; | 2029 LOG(INFO) << "All done. Successfully created delta file."; |
1585 return true; | 2030 return true; |
1586 } | 2031 } |
1587 | 2032 |
1588 const char* const kBsdiffPath = "bsdiff"; | 2033 const char* const kBsdiffPath = "bsdiff"; |
1589 const char* const kBspatchPath = "bspatch"; | 2034 const char* const kBspatchPath = "bspatch"; |
1590 const char* const kDeltaMagic = "CrAU"; | 2035 const char* const kDeltaMagic = "CrAU"; |
1591 | 2036 |
1592 }; // namespace chromeos_update_engine | 2037 }; // namespace chromeos_update_engine |
OLD | NEW |