libsnapshot: Add Sequence Ops
This adds the ability to write sequence ops. A Sequence op is a list of
block values in the new image. These ops may have dependencies on data
that is overwritten by future ops, so must be merged in a specific
order, regardless of their order in the cow file.
This patch only introduces the operation. The following patches will
actually make use of it.
Bug: 177104308
Test: Builds
Change-Id: I9162b49e5061079416ac9e5661c8b1245298044b
diff --git a/fs_mgr/libsnapshot/cow_format.cpp b/fs_mgr/libsnapshot/cow_format.cpp
index 0753c49..20672b3 100644
--- a/fs_mgr/libsnapshot/cow_format.cpp
+++ b/fs_mgr/libsnapshot/cow_format.cpp
@@ -37,6 +37,8 @@
os << "kCowLabelOp, ";
else if (op.type == kCowClusterOp)
os << "kCowClusterOp ";
+ else if (op.type == kCowSequenceOp)
+ os << "kCowSequenceOp ";
else if (op.type == kCowFooterOp)
os << "kCowFooterOp ";
else
@@ -81,6 +83,7 @@
case kCowLabelOp:
case kCowClusterOp:
case kCowFooterOp:
+ case kCowSequenceOp:
return true;
default:
return false;
diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp
index 2349e4a..28ca418 100644
--- a/fs_mgr/libsnapshot/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/cow_reader.cpp
@@ -201,6 +201,8 @@
current_op_num--;
done = true;
break;
+ } else if (current_op.type == kCowSequenceOp) {
+ has_seq_ops_ = true;
}
}
diff --git a/fs_mgr/libsnapshot/cow_writer.cpp b/fs_mgr/libsnapshot/cow_writer.cpp
index 526fede..df2bc96 100644
--- a/fs_mgr/libsnapshot/cow_writer.cpp
+++ b/fs_mgr/libsnapshot/cow_writer.cpp
@@ -76,9 +76,8 @@
return EmitLabel(label);
}
-bool ICowWriter::AddSequenceData(size_t /*num_ops*/, const uint32_t* /*data*/) {
- LOG(ERROR) << "AddSequenceData not yet implemented";
- return false;
+bool ICowWriter::AddSequenceData(size_t num_ops, const uint32_t* data) {
+ return EmitSequenceData(num_ops, data);
}
bool ICowWriter::ValidateNewBlock(uint64_t new_block) {
@@ -337,6 +336,26 @@
return WriteOperation(op) && Sync();
}
+bool CowWriter::EmitSequenceData(size_t num_ops, const uint32_t* data) {
+ CHECK(!merge_in_progress_);
+ size_t to_add = 0;
+ size_t max_ops = std::numeric_limits<uint16_t>::max() / sizeof(uint32_t);
+ while (num_ops > 0) {
+ CowOperation op = {};
+ op.type = kCowSequenceOp;
+ op.source = next_data_pos_;
+ to_add = std::min(num_ops, max_ops);
+ op.data_length = static_cast<uint16_t>(to_add * sizeof(uint32_t));
+ if (!WriteOperation(op, data, op.data_length)) {
+ PLOG(ERROR) << "AddSequenceData: write failed";
+ return false;
+ }
+ num_ops -= to_add;
+ data += to_add;
+ }
+ return true;
+}
+
bool CowWriter::EmitCluster() {
CowOperation op = {};
op.type = kCowClusterOp;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index 000e5e1..2371377 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -148,6 +148,7 @@
static constexpr uint8_t kCowZeroOp = 3;
static constexpr uint8_t kCowLabelOp = 4;
static constexpr uint8_t kCowClusterOp = 5;
+static constexpr uint8_t kCowSequenceOp = 7;
static constexpr uint8_t kCowFooterOp = -1;
static constexpr uint8_t kCowCompressNone = 0;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index 669e58a..16899c0 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -165,6 +165,7 @@
std::shared_ptr<std::vector<CowOperation>> ops_;
uint64_t total_data_ops_;
uint64_t copy_ops_;
+ bool has_seq_ops_;
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
index fbe6461..03ffb46 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
@@ -85,6 +85,7 @@
virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) = 0;
virtual bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) = 0;
virtual bool EmitLabel(uint64_t label) = 0;
+ virtual bool EmitSequenceData(size_t num_ops, const uint32_t* data) = 0;
bool ValidateNewBlock(uint64_t new_block);
@@ -120,6 +121,7 @@
virtual bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
virtual bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
virtual bool EmitLabel(uint64_t label) override;
+ virtual bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
private:
bool EmitCluster();
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
index bf5ce8b..c00dafa 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h
@@ -76,6 +76,7 @@
bool EmitRawBlocks(uint64_t new_block_start, const void* data, size_t size) override;
bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
bool EmitLabel(uint64_t label) override;
+ bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
private:
android::base::unique_fd cow_device_;
@@ -103,6 +104,7 @@
bool EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) override;
bool EmitCopy(uint64_t new_block, uint64_t old_block) override;
bool EmitLabel(uint64_t label) override;
+ bool EmitSequenceData(size_t num_ops, const uint32_t* data) override;
private:
android::base::unique_fd snapshot_fd_;
diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp
index 080f3b7..34b3e87 100644
--- a/fs_mgr/libsnapshot/snapshot_writer.cpp
+++ b/fs_mgr/libsnapshot/snapshot_writer.cpp
@@ -114,6 +114,10 @@
return cow_->AddLabel(label);
}
+bool CompressedSnapshotWriter::EmitSequenceData(size_t num_ops, const uint32_t* data) {
+ return cow_->AddSequenceData(num_ops, data);
+}
+
bool CompressedSnapshotWriter::Initialize() {
return cow_->Initialize(cow_device_);
}
@@ -183,6 +187,11 @@
return true;
}
+bool OnlineKernelSnapshotWriter::EmitSequenceData(size_t, const uint32_t*) {
+ // Not Needed
+ return true;
+}
+
std::unique_ptr<FileDescriptor> OnlineKernelSnapshotWriter::OpenReader() {
unique_fd fd(dup(snapshot_fd_.get()));
if (fd < 0) {