libsnapshot: resume_point_count
We want to add a resume_point_count in the header to represent how many resume points we've written. In the case that we've written less than resume_buffer_size, we only want to read the valid resume points. without these changes incremental OTA runs into segfault or have faulty data when trying to FindResumeOp() as our resume points contain invalid entries Test: full ota followed by inc ota on cuttlefish Change-Id: I0a8971955439639f2d0f39d9d518c1145ae15c3d
This commit is contained in:
parent
a503453767
commit
f897650f6e
4 changed files with 14 additions and 10 deletions
|
@ -107,8 +107,10 @@ static constexpr uint8_t kNumResumePoints = 4;
|
|||
struct CowHeaderV3 : public CowHeader {
|
||||
// Location of sequence buffer in COW.
|
||||
uint64_t sequence_buffer_offset;
|
||||
// number of currently written resume points
|
||||
uint32_t resume_point_count;
|
||||
// Size, in bytes, of the CowResumePoint buffer.
|
||||
uint32_t resume_buffer_size;
|
||||
uint32_t resume_point_max;
|
||||
// Number of CowOperationV3 structs in the operation buffer, currently and total
|
||||
// region size.
|
||||
uint32_t op_count;
|
||||
|
|
|
@ -75,10 +75,10 @@ bool CowParserV3::Parse(borrowed_fd fd, const CowHeaderV3& header, std::optional
|
|||
}
|
||||
|
||||
bool CowParserV3::ReadResumeBuffer(borrowed_fd fd) {
|
||||
resume_points_ = std::make_shared<std::vector<ResumePoint>>(header_.resume_buffer_size);
|
||||
resume_points_ = std::make_shared<std::vector<ResumePoint>>(header_.resume_point_count);
|
||||
|
||||
return android::base::ReadFullyAtOffset(fd, resume_points_->data(),
|
||||
header_.resume_buffer_size * sizeof(ResumePoint),
|
||||
header_.resume_point_count * sizeof(ResumePoint),
|
||||
header_.prefix.header_size + header_.buffer_size);
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ std::optional<uint32_t> CowParserV3::FindResumeOp(const uint64_t label) {
|
|||
|
||||
off_t CowParserV3::GetDataOffset() const {
|
||||
return sizeof(CowHeaderV3) + header_.buffer_size +
|
||||
header_.resume_buffer_size * sizeof(ResumePoint) +
|
||||
header_.resume_point_max * sizeof(ResumePoint) +
|
||||
header_.op_count_max * sizeof(CowOperation);
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ bool CowParserV3::ParseOps(borrowed_fd fd, const uint32_t op_index) {
|
|||
ops_->resize(op_index);
|
||||
|
||||
const off_t offset = header_.prefix.header_size + header_.buffer_size +
|
||||
header_.resume_buffer_size * sizeof(ResumePoint);
|
||||
header_.resume_point_max * sizeof(ResumePoint);
|
||||
if (!android::base::ReadFullyAtOffset(fd, ops_->data(), ops_->size() * sizeof(CowOperationV3),
|
||||
offset)) {
|
||||
PLOG(ERROR) << "read ops failed";
|
||||
|
|
|
@ -78,7 +78,8 @@ void CowWriterV3::SetupHeaders() {
|
|||
// WIP: not quite sure how some of these are calculated yet, assuming buffer_size is determined
|
||||
// during COW size estimation
|
||||
header_.sequence_buffer_offset = 0;
|
||||
header_.resume_buffer_size = kNumResumePoints;
|
||||
header_.resume_point_count = 0;
|
||||
header_.resume_point_max = kNumResumePoints;
|
||||
header_.op_count = 0;
|
||||
header_.op_count_max = 0;
|
||||
header_.compression_algorithm = kCowCompressNone;
|
||||
|
@ -296,12 +297,13 @@ bool CowWriterV3::EmitLabel(uint64_t label) {
|
|||
resume_points_->end());
|
||||
|
||||
resume_points_->push_back({label, header_.op_count});
|
||||
header_.resume_point_count++;
|
||||
// remove the oldest resume point if resume_buffer is full
|
||||
while (resume_points_->size() > header_.resume_buffer_size) {
|
||||
while (resume_points_->size() > header_.resume_point_max) {
|
||||
resume_points_->erase(resume_points_->begin());
|
||||
}
|
||||
|
||||
CHECK_LE(resume_points_->size(), header_.resume_buffer_size);
|
||||
CHECK_LE(resume_points_->size(), header_.resume_point_max);
|
||||
|
||||
if (!android::base::WriteFullyAtOffset(fd_, resume_points_->data(),
|
||||
resume_points_->size() * sizeof(ResumePoint),
|
||||
|
|
|
@ -52,12 +52,12 @@ class CowWriterV3 : public CowWriterBase {
|
|||
off_t GetOpOffset(uint32_t op_index) const {
|
||||
CHECK_LT(op_index, header_.op_count_max);
|
||||
return header_.prefix.header_size + header_.buffer_size +
|
||||
(header_.resume_buffer_size * sizeof(ResumePoint)) +
|
||||
(header_.resume_point_max * sizeof(ResumePoint)) +
|
||||
(op_index * sizeof(CowOperationV3));
|
||||
}
|
||||
off_t GetDataOffset() const {
|
||||
return sizeof(CowHeaderV3) + header_.buffer_size +
|
||||
(header_.resume_buffer_size * sizeof(ResumePoint)) +
|
||||
(header_.resume_point_max * sizeof(ResumePoint)) +
|
||||
header_.op_count_max * sizeof(CowOperation);
|
||||
}
|
||||
off_t GetResumeOffset() const { return sizeof(CowHeaderV3) + header_.buffer_size; }
|
||||
|
|
Loading…
Reference in a new issue