aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Wang2017-08-02 12:27:31 -0500
committerTao Bao2017-08-10 00:59:16 -0500
commit5226f4715d6c961311249552f7e41d68ae2e80e6 (patch)
treecb295bf1e1f06f911b9ab4ab57d88928f3241b9c /update_verifier/update_verifier.cpp
parent05b2e982adcf0afeaedf6c9d785ac1432d84dabd (diff)
downloadplatform-bootable-recovery-5226f4715d6c961311249552f7e41d68ae2e80e6.tar.gz
platform-bootable-recovery-5226f4715d6c961311249552f7e41d68ae2e80e6.tar.xz
platform-bootable-recovery-5226f4715d6c961311249552f7e41d68ae2e80e6.zip
update_verifier: verify blocks in parallel
This CL is to change update_verifier to verify blocks in parallel to maximize storage bandwidth, it also preallocate the buffer to avoid vector allocation within reading loop. Test: care_map.txt: system 16,0,517,556,32770,33084,98306,98620,163842,164156,229378,229692,294914,295228,483544,524288,524296 vendor 8,0,119,135,32770,32831,96150,98304,98306 With CL: init: Service 'update_verifier_nonencrypted' (pid 711) exited with status 0 waiting took 2.978424 seconds Without CL: init: Service 'update_verifier_nonencrypted' (pid 695) exited with status 0 waiting took 4.466320 seconds Bug: 63686531 Test: reboot with manual insert care_map.txt Change-Id: Idf791865f15f6ff6cad89bf7ff230ee46c6adccc (cherry picked from commit bd9664b5a01c8941949212973ca12be4df1b5d54)
Diffstat (limited to 'update_verifier/update_verifier.cpp')
-rw-r--r--update_verifier/update_verifier.cpp82
1 files changed, 51 insertions, 31 deletions
diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp
index 4c3cc46c..faebbede 100644
--- a/update_verifier/update_verifier.cpp
+++ b/update_verifier/update_verifier.cpp
@@ -45,6 +45,7 @@
45#include <unistd.h> 45#include <unistd.h>
46 46
47#include <algorithm> 47#include <algorithm>
48#include <future>
48#include <string> 49#include <string>
49#include <vector> 50#include <vector>
50 51
@@ -123,11 +124,6 @@ static bool read_blocks(const std::string& partition, const std::string& range_s
123 LOG(ERROR) << "Failed to find dm block device for " << partition; 124 LOG(ERROR) << "Failed to find dm block device for " << partition;
124 return false; 125 return false;
125 } 126 }
126 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dm_block_device.c_str(), O_RDONLY)));
127 if (fd.get() == -1) {
128 PLOG(ERROR) << "Error reading " << dm_block_device << " for partition " << partition;
129 return false;
130 }
131 127
132 // For block range string, first integer 'count' equals 2 * total number of valid ranges, 128 // For block range string, first integer 'count' equals 2 * total number of valid ranges,
133 // followed by 'count' number comma separated integers. Every two integers reprensent a 129 // followed by 'count' number comma separated integers. Every two integers reprensent a
@@ -142,37 +138,61 @@ static bool read_blocks(const std::string& partition, const std::string& range_s
142 return false; 138 return false;
143 } 139 }
144 140
145 size_t blk_count = 0; 141 std::vector<std::future<bool>> threads;
146 for (size_t i = 1; i < ranges.size(); i += 2) { 142 size_t thread_num = std::thread::hardware_concurrency() ?: 4;
147 unsigned int range_start, range_end; 143 thread_num = std::min(thread_num, range_count / 2);
148 bool parse_status = android::base::ParseUint(ranges[i], &range_start); 144 size_t group_range_count = range_count / thread_num;
149 parse_status = parse_status && android::base::ParseUint(ranges[i + 1], &range_end);
150 if (!parse_status || range_start >= range_end) {
151 LOG(ERROR) << "Invalid range pair " << ranges[i] << ", " << ranges[i + 1];
152 return false;
153 }
154
155 static constexpr size_t BLOCKSIZE = 4096;
156 if (lseek64(fd.get(), static_cast<off64_t>(range_start) * BLOCKSIZE, SEEK_SET) == -1) {
157 PLOG(ERROR) << "lseek to " << range_start << " failed";
158 return false;
159 }
160 145
161 size_t remain = (range_end - range_start) * BLOCKSIZE; 146 for (size_t t = 0; t < thread_num; t++) {
162 while (remain > 0) { 147 auto thread_func = [t, group_range_count, &dm_block_device, &ranges, &partition]() {
163 size_t to_read = std::min(remain, 1024 * BLOCKSIZE); 148 size_t blk_count = 0;
164 std::vector<uint8_t> buf(to_read); 149 static constexpr size_t kBlockSize = 4096;
165 if (!android::base::ReadFully(fd.get(), buf.data(), to_read)) { 150 std::vector<uint8_t> buf(1024 * kBlockSize);
166 PLOG(ERROR) << "Failed to read blocks " << range_start << " to " << range_end; 151 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dm_block_device.c_str(), O_RDONLY)));
152 if (fd.get() == -1) {
153 PLOG(ERROR) << "Error reading " << dm_block_device << " for partition " << partition;
167 return false; 154 return false;
168 } 155 }
169 remain -= to_read; 156
170 } 157 for (size_t i = 1 + group_range_count * t; i < group_range_count * (t + 1) + 1; i += 2) {
171 blk_count += (range_end - range_start); 158 unsigned int range_start, range_end;
159 bool parse_status = android::base::ParseUint(ranges[i], &range_start);
160 parse_status = parse_status && android::base::ParseUint(ranges[i + 1], &range_end);
161 if (!parse_status || range_start >= range_end) {
162 LOG(ERROR) << "Invalid range pair " << ranges[i] << ", " << ranges[i + 1];
163 return false;
164 }
165
166 if (lseek64(fd.get(), static_cast<off64_t>(range_start) * kBlockSize, SEEK_SET) == -1) {
167 PLOG(ERROR) << "lseek to " << range_start << " failed";
168 return false;
169 }
170
171 size_t remain = (range_end - range_start) * kBlockSize;
172 while (remain > 0) {
173 size_t to_read = std::min(remain, 1024 * kBlockSize);
174 if (!android::base::ReadFully(fd.get(), buf.data(), to_read)) {
175 PLOG(ERROR) << "Failed to read blocks " << range_start << " to " << range_end;
176 return false;
177 }
178 remain -= to_read;
179 }
180 blk_count += (range_end - range_start);
181 }
182 LOG(INFO) << "Finished reading " << blk_count << " blocks on " << dm_block_device;
183 return true;
184 };
185
186 threads.emplace_back(std::async(std::launch::async, thread_func));
172 } 187 }
173 188
174 LOG(INFO) << "Finished reading " << blk_count << " blocks on " << dm_block_device; 189 bool ret = true;
175 return true; 190 for (auto& t : threads) {
191 ret = t.get() && ret;
192 }
193 LOG(INFO) << "Finished reading blocks on " << dm_block_device << " with " << thread_num
194 << " threads.";
195 return ret;
176} 196}
177 197
178// Returns true to indicate a passing verification (or the error should be ignored); Otherwise 198// Returns true to indicate a passing verification (or the error should be ignored); Otherwise