libsnapshot: Clone worker readers from snapuserd

We'll need to have the Cow Files parsed to deal with xor ops, since
their data location is implicit from the format. Since the relevant data
is all stored in shared pointers, we can pass that data into the workers
without needing to reparse or copy.

Bug: 177104308
Test: builds
Change-Id: I96ac3da1ae620be48e5340c9f146c523b3ce74b6
This commit is contained in:
Daniel Rosenberg 2021-07-09 19:17:55 -07:00
parent d83b2efb12
commit d091522de9
5 changed files with 32 additions and 5 deletions

View file

@ -45,6 +45,23 @@ static void SHA256(const void*, size_t, uint8_t[]) {
#endif
}
std::unique_ptr<CowReader> CowReader::CloneCowReader() {
auto cow = std::make_unique<CowReader>();
cow->owned_fd_.reset();
cow->header_ = header_;
cow->footer_ = footer_;
cow->fd_size_ = fd_size_;
cow->last_label_ = last_label_;
cow->ops_ = ops_;
cow->merge_op_blocks_ = merge_op_blocks_;
cow->block_map_ = block_map_;
cow->num_total_data_ops_ = num_total_data_ops_;
cow->num_ordered_ops_to_merge_ = num_ordered_ops_to_merge_;
cow->has_seq_ops_ = has_seq_ops_;
cow->data_loc_ = data_loc_;
return cow;
}
bool CowReader::InitForMerge(android::base::unique_fd&& fd) {
owned_fd_ = std::move(fd);
fd_ = owned_fd_.get();
@ -138,6 +155,7 @@ bool CowReader::Parse(android::base::borrowed_fd fd, std::optional<uint64_t> lab
bool CowReader::ParseOps(std::optional<uint64_t> label) {
uint64_t pos;
auto data_loc = std::make_shared<std::unordered_map<uint64_t, uint64_t>>();
// Skip the scratch space
if (header_.major_version >= 2 && (header_.buffer_size > 0)) {
@ -185,7 +203,7 @@ bool CowReader::ParseOps(std::optional<uint64_t> label) {
auto& current_op = ops_buffer->data()[current_op_num];
current_op_num++;
if (current_op.type == kCowXorOp) {
data_loc_[current_op.new_block] = data_pos;
data_loc->insert({current_op.new_block, data_pos});
}
pos += sizeof(CowOperation) + GetNextOpOffset(current_op, header_.cluster_ops);
data_pos += current_op.data_length + GetNextDataOffset(current_op, header_.cluster_ops);
@ -279,6 +297,7 @@ bool CowReader::ParseOps(std::optional<uint64_t> label) {
ops_ = ops_buffer;
ops_->shrink_to_fit();
data_loc_ = data_loc;
return true;
}
@ -619,7 +638,7 @@ bool CowReader::ReadData(const CowOperation& op, IByteSink* sink) {
uint64_t offset;
if (op.type == kCowXorOp) {
offset = data_loc_[op.new_block];
offset = data_loc_->at(op.new_block);
} else {
offset = op.source;
}

View file

@ -136,6 +136,9 @@ class CowReader : public ICowReader {
void CloseCowFd() { owned_fd_ = {}; }
// Creates a clone of the current CowReader without the file handlers
std::unique_ptr<CowReader> CloneCowReader();
private:
bool ParseOps(std::optional<uint64_t> label);
bool PrepMergeOps();
@ -153,7 +156,7 @@ class CowReader : public ICowReader {
uint64_t num_total_data_ops_;
uint64_t num_ordered_ops_to_merge_;
bool has_seq_ops_;
std::unordered_map<uint64_t, uint64_t> data_loc_;
std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc_;
};
} // namespace snapshot

View file

@ -53,6 +53,10 @@ bool Snapuserd::InitializeWorkers() {
return true;
}
std::unique_ptr<CowReader> Snapuserd::CloneReaderForWorker() {
return reader_->CloneCowReader();
}
bool Snapuserd::CommitMerge(int num_merge_ops) {
struct CowHeader* ch = reinterpret_cast<struct CowHeader*>(mapped_addr_);
ch->num_merge_ops += num_merge_ops;

View file

@ -244,6 +244,7 @@ class Snapuserd : public std::enable_shared_from_this<Snapuserd> {
void* GetExceptionBuffer(size_t i) { return vec_[i].get(); }
bool InitializeWorkers();
std::unique_ptr<CowReader> CloneReaderForWorker();
std::shared_ptr<Snapuserd> GetSharedPtr() { return shared_from_this(); }
std::vector<std::pair<sector_t, const CowOperation*>>& GetChunkVec() { return chunk_vec_; }

View file

@ -105,11 +105,11 @@ bool WorkerThread::InitializeFds() {
}
bool WorkerThread::InitReader() {
reader_ = std::make_unique<CowReader>();
reader_ = snapuserd_->CloneReaderForWorker();
if (!reader_->InitForMerge(std::move(cow_fd_))) {
return false;
}
return true;
}