Loading fs_mgr/libsnapshot/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ cc_library_static { "libsnapshot_cow/cow_format.cpp", "libsnapshot_cow/cow_reader.cpp", "libsnapshot_cow/parser_v2.cpp", "libsnapshot_cow/parser_v3.cpp", "libsnapshot_cow/snapshot_reader.cpp", "libsnapshot_cow/writer_base.cpp", "libsnapshot_cow/writer_v2.cpp", Loading fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h +0 −1 Original line number Diff line number Diff line Loading @@ -185,7 +185,6 @@ class CowReader final : public ICowReader { std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc_; ReaderFlags reader_flag_; bool is_merge_{}; uint8_t compression_type_ = kCowCompressNone; }; // Though this function takes in a CowHeaderV3, the struct could be populated as a v1/v2 CowHeader. Loading fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp +30 −46 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ #include <zlib.h> #include "cow_decompress.h" #include "libsnapshot/cow_format.h" #include "parser_v2.h" namespace android { Loading Loading @@ -85,7 +84,6 @@ std::unique_ptr<CowReader> CowReader::CloneCowReader() { cow->data_loc_ = data_loc_; cow->block_pos_index_ = block_pos_index_; cow->is_merge_ = is_merge_; cow->compression_type_ = compression_type_; return cow; } Loading @@ -104,11 +102,14 @@ bool CowReader::InitForMerge(android::base::unique_fd&& fd) { PLOG(ERROR) << "lseek header failed"; return false; } if (!android::base::ReadFully(fd_, &header_, sizeof(header_))) { CHECK_GE(header_.prefix.header_size, sizeof(CowHeader)); CHECK_LE(header_.prefix.header_size, sizeof(header_)); if (!android::base::ReadFully(fd_, &header_, header_.prefix.header_size)) { PLOG(ERROR) << "read header failed"; return false; } return true; } Loading @@ -124,51 +125,34 @@ bool CowReader::Parse(android::base::borrowed_fd fd, std::optional<uint64_t> lab return false; } CowParserV2 parser; if (!parser.Parse(fd, header_, label)) { std::unique_ptr<CowParserBase> parser; switch (header_.prefix.major_version) { case 1: case 2: parser = std::make_unique<CowParserV2>(); break; case 3: break; default: LOG(ERROR) << "Unknown version: " << header_.prefix.major_version; return false; } footer_ = parser.footer(); fd_size_ = parser.fd_size(); last_label_ = parser.last_label(); data_loc_ = parser.data_loc(); ops_ = std::make_shared<std::vector<CowOperation>>(parser.ops()->size()); // Translate the operation buffer from on disk to in memory for (size_t i = 0; i < parser.ops()->size(); i++) { const auto& v2_op = parser.ops()->at(i); auto& new_op = ops_->at(i); new_op.type = v2_op.type; new_op.data_length = v2_op.data_length; if (v2_op.new_block > std::numeric_limits<uint32_t>::max()) { LOG(ERROR) << "Out-of-range new block in COW op: " << v2_op; if (!parser->Parse(fd, header_, label)) { return false; } new_op.new_block = v2_op.new_block; uint64_t source_info = v2_op.source; if (new_op.type != kCowLabelOp) { source_info &= kCowOpSourceInfoDataMask; if (source_info != v2_op.source) { LOG(ERROR) << "Out-of-range source value in COW op: " << v2_op; return false; } } if (v2_op.compression != kCowCompressNone) { if (compression_type_ == kCowCompressNone) { compression_type_ = v2_op.compression; } else if (compression_type_ != v2_op.compression) { LOG(ERROR) << "COW has mixed compression types which is not supported;" << " previously saw " << compression_type_ << ", got " << v2_op.compression << ", op: " << v2_op; TranslatedCowOps ops_info; if (!parser->Translate(&ops_info)) { return false; } } new_op.source_info = source_info; } header_ = ops_info.header; ops_ = std::move(ops_info.ops); footer_ = parser->footer(); fd_size_ = parser->fd_size(); last_label_ = parser->last_label(); data_loc_ = parser->data_loc(); // If we're resuming a write, we're not ready to merge if (label.has_value()) return true; Loading Loading @@ -664,7 +648,7 @@ class CowDataStream final : public IByteStream { }; uint8_t CowReader::GetCompressionType() { return compression_type_; return header_.compression_algorithm; } ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_size, Loading fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -74,13 +74,13 @@ static void ShowBad(CowReader& reader, const CowOperation* op) { } } static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeader& header) { static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeaderV3& header) { CowParserV2 parser; if (!parser.Parse(fd, header)) { LOG(ERROR) << "v2 parser failed"; return false; } for (const auto& op : *parser.ops()) { for (const auto& op : *parser.get_v2ops()) { std::cout << op << "\n"; if (auto iter = parser.data_loc()->find(op.new_block); iter != parser.data_loc()->end()) { std::cout << " data loc: " << iter->second << "\n"; Loading fs_mgr/libsnapshot/libsnapshot_cow/parser_base.h 0 → 100644 +53 −0 Original line number Diff line number Diff line // // Copyright (C) 2023 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #pragma once #include <optional> #include <unordered_map> #include <android-base/unique_fd.h> #include <libsnapshot/cow_format.h> namespace android { namespace snapshot { struct TranslatedCowOps { CowHeaderV3 header; std::shared_ptr<std::vector<CowOperationV3>> ops; }; class CowParserBase { public: virtual ~CowParserBase() = default; virtual bool Parse(android::base::borrowed_fd fd, const CowHeaderV3& header, std::optional<uint64_t> label = {}) = 0; virtual bool Translate(TranslatedCowOps* out) = 0; virtual std::optional<CowFooter> footer() const { return std::nullopt; } virtual std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc() const = 0; uint64_t fd_size() const { return fd_size_; } const std::optional<uint64_t>& last_label() const { return last_label_; } protected: CowHeaderV3 header_ = {}; uint64_t fd_size_; std::optional<uint64_t> last_label_; }; } // namespace snapshot } // namespace android Loading
fs_mgr/libsnapshot/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -198,6 +198,7 @@ cc_library_static { "libsnapshot_cow/cow_format.cpp", "libsnapshot_cow/cow_reader.cpp", "libsnapshot_cow/parser_v2.cpp", "libsnapshot_cow/parser_v3.cpp", "libsnapshot_cow/snapshot_reader.cpp", "libsnapshot_cow/writer_base.cpp", "libsnapshot_cow/writer_v2.cpp", Loading
fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h +0 −1 Original line number Diff line number Diff line Loading @@ -185,7 +185,6 @@ class CowReader final : public ICowReader { std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc_; ReaderFlags reader_flag_; bool is_merge_{}; uint8_t compression_type_ = kCowCompressNone; }; // Though this function takes in a CowHeaderV3, the struct could be populated as a v1/v2 CowHeader. Loading
fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp +30 −46 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ #include <zlib.h> #include "cow_decompress.h" #include "libsnapshot/cow_format.h" #include "parser_v2.h" namespace android { Loading Loading @@ -85,7 +84,6 @@ std::unique_ptr<CowReader> CowReader::CloneCowReader() { cow->data_loc_ = data_loc_; cow->block_pos_index_ = block_pos_index_; cow->is_merge_ = is_merge_; cow->compression_type_ = compression_type_; return cow; } Loading @@ -104,11 +102,14 @@ bool CowReader::InitForMerge(android::base::unique_fd&& fd) { PLOG(ERROR) << "lseek header failed"; return false; } if (!android::base::ReadFully(fd_, &header_, sizeof(header_))) { CHECK_GE(header_.prefix.header_size, sizeof(CowHeader)); CHECK_LE(header_.prefix.header_size, sizeof(header_)); if (!android::base::ReadFully(fd_, &header_, header_.prefix.header_size)) { PLOG(ERROR) << "read header failed"; return false; } return true; } Loading @@ -124,51 +125,34 @@ bool CowReader::Parse(android::base::borrowed_fd fd, std::optional<uint64_t> lab return false; } CowParserV2 parser; if (!parser.Parse(fd, header_, label)) { std::unique_ptr<CowParserBase> parser; switch (header_.prefix.major_version) { case 1: case 2: parser = std::make_unique<CowParserV2>(); break; case 3: break; default: LOG(ERROR) << "Unknown version: " << header_.prefix.major_version; return false; } footer_ = parser.footer(); fd_size_ = parser.fd_size(); last_label_ = parser.last_label(); data_loc_ = parser.data_loc(); ops_ = std::make_shared<std::vector<CowOperation>>(parser.ops()->size()); // Translate the operation buffer from on disk to in memory for (size_t i = 0; i < parser.ops()->size(); i++) { const auto& v2_op = parser.ops()->at(i); auto& new_op = ops_->at(i); new_op.type = v2_op.type; new_op.data_length = v2_op.data_length; if (v2_op.new_block > std::numeric_limits<uint32_t>::max()) { LOG(ERROR) << "Out-of-range new block in COW op: " << v2_op; if (!parser->Parse(fd, header_, label)) { return false; } new_op.new_block = v2_op.new_block; uint64_t source_info = v2_op.source; if (new_op.type != kCowLabelOp) { source_info &= kCowOpSourceInfoDataMask; if (source_info != v2_op.source) { LOG(ERROR) << "Out-of-range source value in COW op: " << v2_op; return false; } } if (v2_op.compression != kCowCompressNone) { if (compression_type_ == kCowCompressNone) { compression_type_ = v2_op.compression; } else if (compression_type_ != v2_op.compression) { LOG(ERROR) << "COW has mixed compression types which is not supported;" << " previously saw " << compression_type_ << ", got " << v2_op.compression << ", op: " << v2_op; TranslatedCowOps ops_info; if (!parser->Translate(&ops_info)) { return false; } } new_op.source_info = source_info; } header_ = ops_info.header; ops_ = std::move(ops_info.ops); footer_ = parser->footer(); fd_size_ = parser->fd_size(); last_label_ = parser->last_label(); data_loc_ = parser->data_loc(); // If we're resuming a write, we're not ready to merge if (label.has_value()) return true; Loading Loading @@ -664,7 +648,7 @@ class CowDataStream final : public IByteStream { }; uint8_t CowReader::GetCompressionType() { return compression_type_; return header_.compression_algorithm; } ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_size, Loading
fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -74,13 +74,13 @@ static void ShowBad(CowReader& reader, const CowOperation* op) { } } static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeader& header) { static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeaderV3& header) { CowParserV2 parser; if (!parser.Parse(fd, header)) { LOG(ERROR) << "v2 parser failed"; return false; } for (const auto& op : *parser.ops()) { for (const auto& op : *parser.get_v2ops()) { std::cout << op << "\n"; if (auto iter = parser.data_loc()->find(op.new_block); iter != parser.data_loc()->end()) { std::cout << " data loc: " << iter->second << "\n"; Loading
fs_mgr/libsnapshot/libsnapshot_cow/parser_base.h 0 → 100644 +53 −0 Original line number Diff line number Diff line // // Copyright (C) 2023 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #pragma once #include <optional> #include <unordered_map> #include <android-base/unique_fd.h> #include <libsnapshot/cow_format.h> namespace android { namespace snapshot { struct TranslatedCowOps { CowHeaderV3 header; std::shared_ptr<std::vector<CowOperationV3>> ops; }; class CowParserBase { public: virtual ~CowParserBase() = default; virtual bool Parse(android::base::borrowed_fd fd, const CowHeaderV3& header, std::optional<uint64_t> label = {}) = 0; virtual bool Translate(TranslatedCowOps* out) = 0; virtual std::optional<CowFooter> footer() const { return std::nullopt; } virtual std::shared_ptr<std::unordered_map<uint64_t, uint64_t>> data_loc() const = 0; uint64_t fd_size() const { return fd_size_; } const std::optional<uint64_t>& last_label() const { return last_label_; } protected: CowHeaderV3 header_ = {}; uint64_t fd_size_; std::optional<uint64_t> last_label_; }; } // namespace snapshot } // namespace android