V3 writer header
V3 writer set up header. Anything related to cluster ops can be set to
zero, as V3 cow format will no longer support this. All footer related
code can also be dropped as the footer isn't being used.
Test: cow_api_test
Change-Id: I39ece8eaa0813c5991d53b5e0ff9271f27e0662a
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 2b9867e..5ae5f19 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -54,14 +54,116 @@
using android::base::unique_fd;
CowWriterV3::CowWriterV3(const CowOptions& options, unique_fd&& fd)
- : CowWriterBase(options, std::move(fd)) {}
+ : CowWriterBase(options, std::move(fd)) {
+ SetupHeaders();
+}
+
+void CowWriterV3::SetupHeaders() {
+ header_ = {};
+ header_.prefix.magic = kCowMagicNumber;
+ header_.prefix.major_version = 3;
+ header_.prefix.minor_version = 0;
+ header_.prefix.header_size = sizeof(CowHeaderV3);
+ header_.footer_size = 0;
+ header_.op_size = sizeof(CowOperationV3);
+ header_.block_size = options_.block_size;
+ header_.num_merge_ops = options_.num_merge_ops;
+ header_.cluster_ops = 0;
+ if (options_.scratch_space) {
+ header_.buffer_size = BUFFER_REGION_DEFAULT_SIZE;
+ }
+
+ // v3 specific fields
+ // 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 = 0;
+ header_.op_buffer_size = 0;
+ header_.compression_algorithm = kCowCompressNone;
+ return;
+}
+
+bool CowWriterV3::ParseOptions() {
+ num_compress_threads_ = std::max(options_.num_compress_threads, 1);
+ auto parts = android::base::Split(options_.compression, ",");
+ if (parts.size() > 2) {
+ LOG(ERROR) << "failed to parse compression parameters: invalid argument count: "
+ << parts.size() << " " << options_.compression;
+ return false;
+ }
+ auto algorithm = CompressionAlgorithmFromString(parts[0]);
+ if (!algorithm) {
+ LOG(ERROR) << "unrecognized compression: " << options_.compression;
+ return false;
+ }
+ if (parts.size() > 1) {
+ if (!android::base::ParseUint(parts[1], &compression_.compression_level)) {
+ LOG(ERROR) << "failed to parse compression level invalid type: " << parts[1];
+ return false;
+ }
+ } else {
+ compression_.compression_level =
+ CompressWorker::GetDefaultCompressionLevel(algorithm.value());
+ }
+
+ compression_.algorithm = *algorithm;
+ return true;
+}
CowWriterV3::~CowWriterV3() {}
bool CowWriterV3::Initialize(std::optional<uint64_t> label) {
- LOG(ERROR) << __LINE__ << " " << __FILE__ << " <- function here should never be called";
- if (label) return false;
- return false;
+ if (!InitFd() || !ParseOptions()) {
+ return false;
+ }
+
+ CHECK(!label.has_value());
+
+ if (!OpenForWrite()) {
+ return false;
+ }
+
+ return true;
+}
+
+bool CowWriterV3::OpenForWrite() {
+ // This limitation is tied to the data field size in CowOperationV2.
+ // Keeping this for V3 writer <- although we
+ if (header_.block_size > std::numeric_limits<uint16_t>::max()) {
+ LOG(ERROR) << "Block size is too large";
+ return false;
+ }
+
+ if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
+ PLOG(ERROR) << "lseek failed";
+ return false;
+ }
+
+ // Headers are not complete, but this ensures the file is at the right
+ // position.
+ if (!android::base::WriteFully(fd_, &header_, sizeof(header_))) {
+ PLOG(ERROR) << "write failed";
+ return false;
+ }
+
+ if (options_.scratch_space) {
+ // Initialize the scratch space
+ std::string data(header_.buffer_size, 0);
+ if (!android::base::WriteFully(fd_, data.data(), header_.buffer_size)) {
+ PLOG(ERROR) << "writing scratch space failed";
+ return false;
+ }
+ }
+
+ if (!Sync()) {
+ LOG(ERROR) << "Header sync failed";
+ return false;
+ }
+
+ next_op_pos_ = 0;
+ next_data_pos_ = 0;
+
+ return true;
}
bool CowWriterV3::EmitCopy(uint64_t new_block, uint64_t old_block, uint64_t num_blocks) {
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
index ddd7287..2a88a12 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
@@ -37,6 +37,22 @@
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:
+ void SetupHeaders();
+ bool ParseOptions();
+ bool OpenForWrite();
+
+ private:
+ CowHeaderV3 header_{};
+ CowCompression compression_;
+ // in the case that we are using one thread for compression, we can store and re-use the same
+ // compressor
+
+ uint64_t next_op_pos_ = 0;
+ uint64_t next_data_pos_ = 0;
+
+ int num_compress_threads_ = 1;
};
} // namespace snapshot