Merge "update_verifier: verify blocks in parallel"
This commit is contained in:
@@ -45,6 +45,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <future>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -123,11 +124,6 @@ static bool read_blocks(const std::string& partition, const std::string& range_s
|
|||||||
LOG(ERROR) << "Failed to find dm block device for " << partition;
|
LOG(ERROR) << "Failed to find dm block device for " << partition;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dm_block_device.c_str(), O_RDONLY)));
|
|
||||||
if (fd.get() == -1) {
|
|
||||||
PLOG(ERROR) << "Error reading " << dm_block_device << " for partition " << partition;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For block range string, first integer 'count' equals 2 * total number of valid ranges,
|
// For block range string, first integer 'count' equals 2 * total number of valid ranges,
|
||||||
// followed by 'count' number comma separated integers. Every two integers reprensent a
|
// 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
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t blk_count = 0;
|
std::vector<std::future<bool>> threads;
|
||||||
for (size_t i = 1; i < ranges.size(); i += 2) {
|
size_t thread_num = std::thread::hardware_concurrency() ?: 4;
|
||||||
unsigned int range_start, range_end;
|
thread_num = std::min(thread_num, range_count / 2);
|
||||||
bool parse_status = android::base::ParseUint(ranges[i], &range_start);
|
size_t group_range_count = range_count / thread_num;
|
||||||
parse_status = parse_status && android::base::ParseUint(ranges[i + 1], &range_end);
|
|
||||||
if (!parse_status || range_start >= range_end) {
|
|
||||||
LOG(ERROR) << "Invalid range pair " << ranges[i] << ", " << ranges[i + 1];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr size_t BLOCKSIZE = 4096;
|
for (size_t t = 0; t < thread_num; t++) {
|
||||||
if (lseek64(fd.get(), static_cast<off64_t>(range_start) * BLOCKSIZE, SEEK_SET) == -1) {
|
auto thread_func = [t, group_range_count, &dm_block_device, &ranges, &partition]() {
|
||||||
PLOG(ERROR) << "lseek to " << range_start << " failed";
|
size_t blk_count = 0;
|
||||||
return false;
|
static constexpr size_t kBlockSize = 4096;
|
||||||
}
|
std::vector<uint8_t> buf(1024 * kBlockSize);
|
||||||
|
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dm_block_device.c_str(), O_RDONLY)));
|
||||||
size_t remain = (range_end - range_start) * BLOCKSIZE;
|
if (fd.get() == -1) {
|
||||||
while (remain > 0) {
|
PLOG(ERROR) << "Error reading " << dm_block_device << " for partition " << partition;
|
||||||
size_t to_read = std::min(remain, 1024 * BLOCKSIZE);
|
|
||||||
std::vector<uint8_t> buf(to_read);
|
|
||||||
if (!android::base::ReadFully(fd.get(), buf.data(), to_read)) {
|
|
||||||
PLOG(ERROR) << "Failed to read blocks " << range_start << " to " << range_end;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
remain -= to_read;
|
|
||||||
}
|
for (size_t i = 1 + group_range_count * t; i < group_range_count * (t + 1) + 1; i += 2) {
|
||||||
blk_count += (range_end - range_start);
|
unsigned int range_start, range_end;
|
||||||
|
bool parse_status = android::base::ParseUint(ranges[i], &range_start);
|
||||||
|
parse_status = parse_status && android::base::ParseUint(ranges[i + 1], &range_end);
|
||||||
|
if (!parse_status || range_start >= range_end) {
|
||||||
|
LOG(ERROR) << "Invalid range pair " << ranges[i] << ", " << ranges[i + 1];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lseek64(fd.get(), static_cast<off64_t>(range_start) * kBlockSize, SEEK_SET) == -1) {
|
||||||
|
PLOG(ERROR) << "lseek to " << range_start << " failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t remain = (range_end - range_start) * kBlockSize;
|
||||||
|
while (remain > 0) {
|
||||||
|
size_t to_read = std::min(remain, 1024 * kBlockSize);
|
||||||
|
if (!android::base::ReadFully(fd.get(), buf.data(), to_read)) {
|
||||||
|
PLOG(ERROR) << "Failed to read blocks " << range_start << " to " << range_end;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
remain -= to_read;
|
||||||
|
}
|
||||||
|
blk_count += (range_end - range_start);
|
||||||
|
}
|
||||||
|
LOG(INFO) << "Finished reading " << blk_count << " blocks on " << dm_block_device;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
threads.emplace_back(std::async(std::launch::async, thread_func));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(INFO) << "Finished reading " << blk_count << " blocks on " << dm_block_device;
|
bool ret = true;
|
||||||
return true;
|
for (auto& t : threads) {
|
||||||
|
ret = t.get() && ret;
|
||||||
|
}
|
||||||
|
LOG(INFO) << "Finished reading blocks on " << dm_block_device << " with " << thread_num
|
||||||
|
<< " threads.";
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true to indicate a passing verification (or the error should be ignored); Otherwise
|
// Returns true to indicate a passing verification (or the error should be ignored); Otherwise
|
||||||
|
|||||||
Reference in New Issue
Block a user