BLOCK升级完整包system.transfer.list中erase、new、zero流程:
走到erase、new、zero说明已经校验OK,进入写BLOCK阶段,具体在BlockImageUpdateFn中实现在updater-script中体现为:block_image_update,方法如下:
Value* BlockImageUpdateFn(const char* name, State* state,const std::vector<std::unique_ptr<Expr>>& argv) {
const CommandMap command_map{
// clang-format off
{ Command::Type::ABORT, PerformCommandAbort },
{ Command::Type::BSDIFF, PerformCommandDiff },
{ Command::Type::COMPUTE_HASH_TREE, PerformCommandComputeHashTree },
{ Command::Type::ERASE, PerformCommandErase },
{ Command::Type::FREE, PerformCommandFree },
{ Command::Type::IMGDIFF, PerformCommandDiff },
{ Command::Type::MOVE, PerformCommandMove },
{ Command::Type::NEW, PerformCommandNew },
{ Command::Type::STASH, PerformCommandStash },
{ Command::Type::ZERO, PerformCommandZero },
// clang-format on
};
CHECK_EQ(static_cast<size_t>(Command::Type::LAST), command_map.size());
return PerformBlockImageUpdate(name, state, argv, command_map, false);
}
将命令对应的方法存入CommandMap,继续看PerformBlockImageUpdate方法实现
static Value* PerformBlockImageUpdate(const char* name, State* state,
const std::vector<std::unique_ptr<Expr>>& argv,
const CommandMap& command_map, bool dryrun) {
...
std::vector<std::string> lines = android::base::Split(transfer_list_value->data, "\n");//解析system.transfer.list文件到lines
...
if (params.canwrite) {//创建写数据线程
params.nti.za = za;
params.nti.entry = new_entry;
params.nti.brotli_compressed = android::base::EndsWith(new_data_fn->data, ".br");
if (params.nti.brotli_compressed) {
// Initialize brotli decoder state.
params.nti.brotli_decoder_state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
}
params.nti.receiver_available = true;
pthread_mutex_init(¶ms.nti.mu, nullptr);
pthread_cond_init(¶ms.nti.cv, nullptr);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//创建线程,receive_brotli_new_data方法内读写数据
int error = pthread_create(¶ms.thread, &attr, unzip_new_data, ¶ms.nti);
if (error != 0) {
LOG(ERROR) << "pthread_create failed: " << strerror(error);
return StringValue("");
}
}
Command::Type cmd_type = Command::ParseType(params.cmdname);//解析命令,
const CommandFunction& performer = command_map.at(cmd_type);//从命令获取方法
if (performer(params) == -1) {//调用对应方法,erase 调用PerformCommandErase,new调用PerformCommandNew,erase调用PerformCommandErase
...
}
}
一、erase 流程:
如:erase 6,134685,163328,164354,228864,229953,257475
static int PerformCommandErase(CommandParameters& params) {
if (DEBUG_ERASE) {
return PerformCommandZero(params);
}
struct stat sb;
if (fstat(params.fd, &sb) == -1) {//文件描述符的状态信息
PLOG(ERROR) << "failed to fstat device to erase";
return -1;
}
if (!S_ISBLK(sb.st_mode)) {
LOG(ERROR) << "not a block device; skipping erase";
return -1;
}
if (params.cpos >= params.tokens.size()) {
LOG(ERROR) << "missing target blocks for erase";
return -1;
}
RangeSet tgt = RangeSet::Parse(params.tokens[params.cpos++]);
CHECK(static_cast<bool>(tgt));
if (params.canwrite) {
LOG(INFO) << " erasing " << tgt.blocks() << " blocks";
for (const auto& [begin, end] : tgt) {//如:[134685,163328]
off64_t offset = static_cast<off64_t>(begin) * BLOCKSIZE;
size_t size = (end - begin) * BLOCKSIZE;//block大小:(163328-134685)*4096=116,548,367
if (!discard_blocks(params.fd, offset, size, true /* force */)) {
return -1;
}
}
}
}
调用discard_blocks丢掉对应的block
static bool discard_blocks(int fd, off64_t offset, uint64_t size, bool force = false) {
// Don't discard blocks unless the update is a retry run or force == true
if (!is_retry && !force) {
return true;
}
uint64_t args[2] = { static_cast<uint64_t>(offset), size };
if (ioctl(fd, BLKDISCARD, &args) == -1) {// 最终调用系统ioctl丢弃指定BLOCK(163328-134685)
// On devices that does not support BLKDISCARD, ignore the error.
if (errno == EOPNOTSUPP) {
return true;
}
PLOG(ERROR) << "BLKDISCARD ioctl failed";
return false;
}
return true;
}
二、zero流程
zero调用PerformCommandZero实现
三、new 流程:
new 调用PerformCommandNew方法
static int PerformCommandNew(CommandParameters& params) {
if (params.cpos >= params.tokens.size()) {
LOG(ERROR) << "missing target blocks for new";
return -1;
}
RangeSet tgt = RangeSet::Parse(params.tokens[params.cpos++]);
CHECK(static_cast<bool>(tgt));
if (params.canwrite) {
LOG(INFO) << " writing " << tgt.blocks() << " blocks of new data";
pthread_mutex_lock(¶ms.nti.mu);
//创建一个RangeSinkWriter包含block范围(RangeSet),在PerformBlockImageUpdate创建的线程中receive_brotli_new_data检测到params.nti.writer不为空则开始执行写动作,写完后将params.nti.writer置空
params.nti.writer = std::make_unique<RangeSinkWriter>(params.fd, tgt);
pthread_cond_broadcast(¶ms.nti.cv);
while (params.nti.writer != nullptr) {//判断是否写完数据
if (!params.nti.receiver_available) {
LOG(ERROR) << "missing " << (tgt.blocks() * BLOCKSIZE - params.nti.writer->BytesWritten())
<< " bytes of new data";
pthread_mutex_unlock(¶ms.nti.mu);
return -1;
}
pthread_cond_wait(¶ms.nti.cv, ¶ms.nti.mu);
}
pthread_mutex_unlock(¶ms.nti.mu);
}
params.written += tgt.blocks();
return 0;
}