Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium 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 #include <sys/stat.h> | 6 #include <sys/stat.h> |
| 7 #include <sys/types.h> | 7 #include <sys/types.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <set> | 11 #include <set> |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 33 using std::set; | 33 using std::set; |
| 34 using std::string; | 34 using std::string; |
| 35 using std::vector; | 35 using std::vector; |
| 36 | 36 |
| 37 namespace chromeos_update_engine { | 37 namespace chromeos_update_engine { |
| 38 | 38 |
| 39 typedef DeltaDiffGenerator::Block Block; | 39 typedef DeltaDiffGenerator::Block Block; |
| 40 | 40 |
| 41 namespace { | 41 namespace { |
| 42 const size_t kBlockSize = 4096; | 42 const size_t kBlockSize = 4096; |
| 43 const size_t kRootFSPartitionSize = 1 * 1024 * 1024 * 1024; // 1 GiB | |
|
Will Drewry
2010/09/29 01:10:47
Any chance you could open(tgt), ioctl(BLKGETSIZE64
petkov
2010/09/29 04:27:40
I don't think I can do this -- this is running on
Will Drewry
2010/09/29 04:33:41
Hrm the size is definitely available in the gpt ta
petkov
2010/09/29 16:17:36
$ cgpt show chromiumos_base_image.bin | fgrep ROOT
Will Drewry
2010/09/29 19:07:36
It being hard-coded in the installer means we get
petkov
2010/09/29 19:44:35
crosbug/7181 filed.
| |
| 43 const uint64_t kVersionNumber = 1; | 44 const uint64_t kVersionNumber = 1; |
| 44 | 45 |
| 45 // Stores all Extents for a file into 'out'. Returns true on success. | 46 // Stores all Extents for a file into 'out'. Returns true on success. |
| 46 bool GatherExtents(const string& path, | 47 bool GatherExtents(const string& path, |
| 47 google::protobuf::RepeatedPtrField<Extent>* out) { | 48 google::protobuf::RepeatedPtrField<Extent>* out) { |
| 48 vector<Extent> extents; | 49 vector<Extent> extents; |
| 49 TEST_AND_RETURN_FALSE(extent_mapper::ExtentsForFileFibmap(path, &extents)); | 50 TEST_AND_RETURN_FALSE(extent_mapper::ExtentsForFileFibmap(path, &extents)); |
| 50 DeltaDiffGenerator::StoreExtents(extents, out); | 51 DeltaDiffGenerator::StoreExtents(extents, out); |
| 51 return true; | 52 return true; |
| 52 } | 53 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 blocks, | 203 blocks, |
| 203 old_root, | 204 old_root, |
| 204 new_root, | 205 new_root, |
| 205 fs_iter.GetPartialPath(), | 206 fs_iter.GetPartialPath(), |
| 206 data_fd, | 207 data_fd, |
| 207 data_file_size)); | 208 data_file_size)); |
| 208 } | 209 } |
| 209 return true; | 210 return true; |
| 210 } | 211 } |
| 211 | 212 |
| 212 // Attempts to find block_count blocks to use as scratch space. | 213 // Attempts to find |block_count| blocks to use as scratch space. Returns true |
| 213 // Returns true on success. | 214 // on success. Right now we return exactly as many blocks as are required. |
| 214 // Right now we return exactly as many blocks as are required. | 215 // |
| 215 // TODO(adlr): consider returning all scratch blocks, | 216 // TODO(adlr): Consider returning all scratch blocks, even if there are extras, |
| 216 // even if there are extras, to make it easier for a scratch allocator | 217 // to make it easier for a scratch allocator to find contiguous regions for |
| 217 // to find contiguous regions for specific scratch writes. | 218 // specific scratch writes. |
| 218 bool FindScratchSpace(const vector<Block>& blocks, | 219 bool FindScratchSpace(const vector<Block>& blocks, |
| 219 vector<Block>::size_type block_count, | 220 vector<Block>::size_type block_count, |
| 220 vector<Extent>* out) { | 221 vector<Extent>* out) { |
| 221 // Scan blocks for blocks that are neither read nor written. | 222 // Scan |blocks| for blocks that are neither read, nor written. If we don't |
| 222 // If we don't find enough of those, return false. | 223 // find enough of those, look past the end of |blocks| till the end of the |
| 223 // TODO(adlr): return blocks that are written by | 224 // partition. If we don't find |block_count| scratch blocks, return false. |
| 224 // operations that don't have incoming edges (and thus, can be | 225 // |
| 225 // deferred until all old blocks are read by other operations). | 226 // TODO(adlr): Return blocks that are written by operations that don't have |
| 227 // incoming edges (and thus, can be deferred until all old blocks are read by | |
| 228 // other operations). | |
| 226 vector<Extent> ret; | 229 vector<Extent> ret; |
| 227 vector<Block>::size_type blocks_found = 0; | 230 vector<Block>::size_type blocks_found = 0; |
| 231 const size_t kPartitionBlocks = kRootFSPartitionSize / kBlockSize; | |
| 228 for (vector<Block>::size_type i = 0; | 232 for (vector<Block>::size_type i = 0; |
| 229 i < blocks.size() && blocks_found < block_count; i++) { | 233 i < kPartitionBlocks && blocks_found < block_count; i++) { |
| 230 if (blocks[i].reader == Vertex::kInvalidIndex && | 234 if (i >= blocks.size() || |
| 231 blocks[i].writer == Vertex::kInvalidIndex) { | 235 (blocks[i].reader == Vertex::kInvalidIndex && |
| 236 blocks[i].writer == Vertex::kInvalidIndex)) { | |
| 232 graph_utils::AppendBlockToExtents(&ret, i); | 237 graph_utils::AppendBlockToExtents(&ret, i); |
| 233 blocks_found++; | 238 blocks_found++; |
| 234 } | 239 } |
| 235 } | 240 } |
| 241 LOG(INFO) << "found " << blocks_found << " scratch blocks"; | |
| 236 if (blocks_found == block_count) { | 242 if (blocks_found == block_count) { |
| 237 LOG(INFO) << "returning " << blocks_found << " scratch blocks"; | |
| 238 out->swap(ret); | 243 out->swap(ret); |
| 239 return true; | 244 return true; |
| 240 } | 245 } |
| 241 return false; | 246 return false; |
| 242 } | 247 } |
| 243 | 248 |
| 244 // This class takes a collection of Extents and allows the client to | 249 // This class takes a collection of Extents and allows the client to |
| 245 // allocate space from these extents. The client must not request more | 250 // allocate space from these extents. The client must not request more |
| 246 // space then exists in the source extents. Space is allocated from the | 251 // space then exists in the source extents. Space is allocated from the |
| 247 // beginning of the source extents on; no consideration is paid to | 252 // beginning of the source extents on; no consideration is paid to |
| (...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 867 manifest.kernel_install_operations_size()); i++) { | 872 manifest.kernel_install_operations_size()); i++) { |
| 868 DeltaArchiveManifest_InstallOperation* op = | 873 DeltaArchiveManifest_InstallOperation* op = |
| 869 i < manifest.install_operations_size() ? | 874 i < manifest.install_operations_size() ? |
| 870 manifest.mutable_install_operations(i) : | 875 manifest.mutable_install_operations(i) : |
| 871 manifest.mutable_kernel_install_operations( | 876 manifest.mutable_kernel_install_operations( |
| 872 i - manifest.install_operations_size()); | 877 i - manifest.install_operations_size()); |
| 873 for (int j = 0; j < op->dst_extents_size(); j++) { | 878 for (int j = 0; j < op->dst_extents_size(); j++) { |
| 874 const Extent& extent = op->dst_extents(j); | 879 const Extent& extent = op->dst_extents(j); |
| 875 for (uint64_t block = extent.start_block(); | 880 for (uint64_t block = extent.start_block(); |
| 876 block < (extent.start_block() + extent.num_blocks()); block++) { | 881 block < (extent.start_block() + extent.num_blocks()); block++) { |
| 877 written_count[block]++; | 882 if (block < blocks.size()) |
|
Will Drewry
2010/09/29 01:10:47
Does this just catch if scratch blocks are written
petkov
2010/09/29 04:27:40
My understanding is that this code makes sure that
Will Drewry
2010/09/29 04:33:41
Fair enough. We can go through that with adlr@ wh
| |
| 883 written_count[block]++; | |
| 878 } | 884 } |
| 879 } | 885 } |
| 880 if (op->has_data_offset()) { | 886 if (op->has_data_offset()) { |
| 881 if (op->data_offset() != next_blob_offset) { | 887 if (op->data_offset() != next_blob_offset) { |
| 882 LOG(FATAL) << "bad blob offset! " << op->data_offset() << " != " | 888 LOG(FATAL) << "bad blob offset! " << op->data_offset() << " != " |
| 883 << next_blob_offset; | 889 << next_blob_offset; |
| 884 } | 890 } |
| 885 next_blob_offset += op->data_length(); | 891 next_blob_offset += op->data_length(); |
| 886 } | 892 } |
| 887 } | 893 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 980 | 986 |
| 981 LOG(INFO) << "All done. Successfully created delta file."; | 987 LOG(INFO) << "All done. Successfully created delta file."; |
| 982 return true; | 988 return true; |
| 983 } | 989 } |
| 984 | 990 |
| 985 const char* const kBsdiffPath = "/usr/bin/bsdiff"; | 991 const char* const kBsdiffPath = "/usr/bin/bsdiff"; |
| 986 const char* const kBspatchPath = "/usr/bin/bspatch"; | 992 const char* const kBspatchPath = "/usr/bin/bspatch"; |
| 987 const char* const kDeltaMagic = "CrAU"; | 993 const char* const kDeltaMagic = "CrAU"; |
| 988 | 994 |
| 989 }; // namespace chromeos_update_engine | 995 }; // namespace chromeos_update_engine |
| OLD | NEW |