diff --git a/fastboot/Android.bp b/fastboot/Android.bp index e6f9ffaee..81ebf4392 100644 --- a/fastboot/Android.bp +++ b/fastboot/Android.bp @@ -147,7 +147,6 @@ cc_binary { static_libs: [ "libgtest_prod", "libhealthhalutils", - "libsnapshot_cow", "libsnapshot_nobinder", "update_metadata-protos", ], diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp index ddffef295..db2e16ce3 100644 --- a/fs_mgr/libsnapshot/Android.bp +++ b/fs_mgr/libsnapshot/Android.bp @@ -74,11 +74,9 @@ filegroup { "android/snapshot/snapshot.proto", "device_info.cpp", "snapshot.cpp", - "snapshot_reader.cpp", "snapshot_stats.cpp", "snapshot_stub.cpp", "snapshot_metadata_updater.cpp", - "snapshot_writer.cpp", "partition_cow_creator.cpp", "return.cpp", "utility.cpp", @@ -249,7 +247,6 @@ cc_defaults { "libgmock", "liblp", "libsnapshot", - "libsnapshot_cow", "libsnapshot_test_helpers", "libsparse", ], @@ -284,7 +281,6 @@ cc_binary { static_libs: [ "libfstab", "libsnapshot", - "libsnapshot_cow", "update_metadata-protos", ], shared_libs: [ @@ -348,7 +344,6 @@ cc_defaults { "libgmock", // from libsnapshot_test_helpers "liblog", "liblp", - "libsnapshot_cow", "libsnapshot_test_helpers", "libprotobuf-mutator", ], diff --git a/fs_mgr/libsnapshot/cow_writer.cpp b/fs_mgr/libsnapshot/cow_writer.cpp index f96f174c5..70fdac197 100644 --- a/fs_mgr/libsnapshot/cow_writer.cpp +++ b/fs_mgr/libsnapshot/cow_writer.cpp @@ -32,9 +32,6 @@ namespace snapshot { static_assert(sizeof(off_t) == sizeof(uint64_t)); -using android::base::borrowed_fd; -using android::base::unique_fd; - bool ICowWriter::AddCopy(uint64_t new_block, uint64_t old_block) { if (!ValidateNewBlock(new_block)) { return false; @@ -101,12 +98,12 @@ bool CowWriter::ParseOptions() { return true; } -bool CowWriter::Initialize(unique_fd&& fd, OpenMode mode) { +bool CowWriter::Initialize(android::base::unique_fd&& fd, OpenMode mode) { owned_fd_ = std::move(fd); - return Initialize(borrowed_fd{owned_fd_}, mode); + return Initialize(android::base::borrowed_fd{owned_fd_}, mode); } -bool CowWriter::Initialize(borrowed_fd fd, OpenMode mode) { +bool CowWriter::Initialize(android::base::borrowed_fd fd, OpenMode mode) { fd_ = fd; if (!ParseOptions()) { diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h index 2bc017100..245da0c7d 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h @@ -58,9 +58,6 @@ class ICowWriter { // Return number of bytes the cow image occupies on disk. virtual uint64_t GetCowSize() = 0; - // Returns true if AddCopy() operations are supported. - virtual bool SupportsCopyOperation() const { return true; } - const CowOptions& options() { return options_; } protected: diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h index 13f19aa87..eb6ad0537 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h @@ -38,7 +38,9 @@ class MockSnapshotManager : public ISnapshotManager { (const android::fs_mgr::CreateLogicalPartitionParams& params, std::string* snapshot_path), (override)); - MOCK_METHOD(std::unique_ptr, OpenSnapshotWriter, + MOCK_METHOD(std::unique_ptr, OpenSnapshotWriter, + (const android::fs_mgr::CreateLogicalPartitionParams& params), (override)); + MOCK_METHOD(std::unique_ptr, OpenSnapshotReader, (const android::fs_mgr::CreateLogicalPartitionParams& params), (override)); MOCK_METHOD(bool, UnmapUpdateSnapshot, (const std::string& target_partition_name), (override)); MOCK_METHOD(bool, NeedSnapshotsInFirstStageMount, (), (override)); diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h index 1bc972e9a..6fef58a7f 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h @@ -35,8 +35,8 @@ #include #include +#include #include -#include #ifndef FRIEND_TEST #define FRIEND_TEST(test_set_name, individual_test) \ @@ -44,6 +44,10 @@ #define DEFINED_FRIEND_TEST #endif +namespace chromeos_update_engine { +class FileDescriptor; +} // namespace chromeos_update_engine + namespace android { namespace fiemap { @@ -106,6 +110,8 @@ class ISnapshotManager { }; virtual ~ISnapshotManager() = default; + using FileDescriptor = chromeos_update_engine::FileDescriptor; + // Begin an update. This must be called before creating any snapshots. It // will fail if GetUpdateState() != None. virtual bool BeginUpdate() = 0; @@ -181,14 +187,19 @@ class ISnapshotManager { virtual bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params, std::string* snapshot_path) = 0; - // Create an ISnapshotWriter to build a snapshot against a target partition. The partition name - // must be suffixed. - virtual std::unique_ptr OpenSnapshotWriter( + // Create an ICowWriter to build a snapshot against a target partition. The partition name must + // be suffixed. + virtual std::unique_ptr OpenSnapshotWriter( + const android::fs_mgr::CreateLogicalPartitionParams& params) = 0; + + // Open a snapshot for reading. A file-like interface is provided through the FileDescriptor. + // In this mode, writes are not supported. The partition name must be suffixed. + virtual std::unique_ptr OpenSnapshotReader( const android::fs_mgr::CreateLogicalPartitionParams& params) = 0; // Unmap a snapshot device or CowWriter that was previously opened with MapUpdateSnapshot, - // OpenSnapshotWriter. All outstanding open descriptors, writers, or - // readers must be deleted before this is called. + // OpenSnapshotWriter, or OpenSnapshotReader. All outstanding open descriptors, writers, + // or readers must be deleted before this is called. virtual bool UnmapUpdateSnapshot(const std::string& target_partition_name) = 0; // If this returns true, first-stage mount must call @@ -299,7 +310,9 @@ class SnapshotManager final : public ISnapshotManager { Return CreateUpdateSnapshots(const DeltaArchiveManifest& manifest) override; bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params, std::string* snapshot_path) override; - std::unique_ptr OpenSnapshotWriter( + std::unique_ptr OpenSnapshotWriter( + const android::fs_mgr::CreateLogicalPartitionParams& params) override; + std::unique_ptr OpenSnapshotReader( const android::fs_mgr::CreateLogicalPartitionParams& params) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool NeedSnapshotsInFirstStageMount() override; @@ -519,39 +532,9 @@ class SnapshotManager final : public ISnapshotManager { std::string GetSnapshotDeviceName(const std::string& snapshot_name, const SnapshotStatus& status); - // Reason for calling MapPartitionWithSnapshot. - enum class SnapshotContext { - // For writing or verification (during update_engine). - Update, - - // For mounting a full readable device. - Mount, - }; - - struct SnapshotPaths { - // Target/base device (eg system_b), always present. - std::string target_device; - - // COW path (eg system_cow). Not present if no COW is needed. - std::string cow_device; - - // dm-snapshot instance. Not present in Update mode for VABC. - std::string snapshot_device; - }; - - // Helpers for OpenSnapshotWriter. - std::unique_ptr OpenCompressedSnapshotWriter(LockedFile* lock, - const std::string& partition_name, - const SnapshotStatus& status, - const SnapshotPaths& paths); - std::unique_ptr OpenKernelSnapshotWriter(LockedFile* lock, - const std::string& partition_name, - const SnapshotStatus& status, - const SnapshotPaths& paths); - // Map the base device, COW devices, and snapshot device. bool MapPartitionWithSnapshot(LockedFile* lock, CreateLogicalPartitionParams params, - SnapshotContext context, SnapshotPaths* paths); + std::string* path); // Map the COW devices, including the partition in super and the images. // |params|: diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h index cda2bee33..149f463a9 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h @@ -36,7 +36,9 @@ class SnapshotManagerStub : public ISnapshotManager { const chromeos_update_engine::DeltaArchiveManifest& manifest) override; bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params, std::string* snapshot_path) override; - std::unique_ptr OpenSnapshotWriter( + std::unique_ptr OpenSnapshotWriter( + const android::fs_mgr::CreateLogicalPartitionParams& params) override; + std::unique_ptr OpenSnapshotReader( const android::fs_mgr::CreateLogicalPartitionParams& params) override; bool UnmapUpdateSnapshot(const std::string& target_partition_name) override; bool NeedSnapshotsInFirstStageMount() override; diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h deleted file mode 100644 index bf57a0078..000000000 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_writer.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (C) 2020 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 - -#include - -namespace chromeos_update_engine { -class FileDescriptor; -} // namespace chromeos_update_engine - -namespace android { -namespace snapshot { - -class ISnapshotWriter : public ICowWriter { - public: - using FileDescriptor = chromeos_update_engine::FileDescriptor; - - explicit ISnapshotWriter(const CowOptions& options); - - // Set the source device. This is used for AddCopy() operations, if the - // underlying writer needs the original bytes (for example if backed by - // dm-snapshot or if writing directly to an unsnapshotted region). - void SetSourceDevice(android::base::unique_fd&& source_fd); - - virtual std::unique_ptr OpenReader() = 0; - - protected: - android::base::unique_fd source_fd_; -}; - -// Write directly to a dm-snapshot device. -class OnlineKernelSnapshotWriter : public ISnapshotWriter { - public: - OnlineKernelSnapshotWriter(const CowOptions& options); - - // Set the device used for all writes. - void SetSnapshotDevice(android::base::unique_fd&& snapshot_fd, uint64_t cow_size); - - bool Flush() override; - uint64_t GetCowSize() override { return cow_size_; } - virtual std::unique_ptr OpenReader() override; - - protected: - 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 EmitCopy(uint64_t new_block, uint64_t old_block) override; - - private: - android::base::unique_fd snapshot_fd_; - uint64_t cow_size_ = 0; -}; - -} // namespace snapshot -} // namespace android diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h index 197aeaa05..8e369b052 100644 --- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h +++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h @@ -144,7 +144,6 @@ void DeleteBackingImage(android::fiemap::IImageManager* manager, const std::stri // Expect space of |path| is multiple of 4K. bool WriteRandomData(const std::string& path, std::optional expect_size = std::nullopt, std::string* hash = nullptr); -bool WriteRandomData(ICowWriter* writer, std::string* hash = nullptr); std::optional GetHash(const std::string& path); diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp index b672d0e28..0904fc76b 100644 --- a/fs_mgr/libsnapshot/snapshot.cpp +++ b/fs_mgr/libsnapshot/snapshot.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -44,7 +43,6 @@ #include "device_info.h" #include "partition_cow_creator.h" #include "snapshot_metadata_updater.h" -#include "snapshot_reader.h" #include "utility.h" namespace android { @@ -1572,8 +1570,7 @@ bool SnapshotManager::CreateLogicalAndSnapshotPartitions( .timeout_ms = timeout_ms, }; std::string ignore_path; - if (!MapPartitionWithSnapshot(lock.get(), std::move(params), SnapshotContext::Mount, - nullptr)) { + if (!MapPartitionWithSnapshot(lock.get(), std::move(params), &ignore_path)) { return false; } } @@ -1601,10 +1598,11 @@ static std::chrono::milliseconds GetRemainingTime( bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, CreateLogicalPartitionParams params, - SnapshotContext context, SnapshotPaths* paths) { + std::string* path) { auto begin = std::chrono::steady_clock::now(); CHECK(lock); + path->clear(); if (params.GetPartitionName() != params.GetDeviceName()) { LOG(ERROR) << "Mapping snapshot with a different name is unsupported: partition_name = " @@ -1685,11 +1683,8 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, } created_devices.EmplaceBack(&dm, params.GetDeviceName()); - if (paths) { - paths->target_device = base_path; - } - if (!live_snapshot_status.has_value()) { + *path = base_path; created_devices.Release(); return true; } @@ -1716,33 +1711,21 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, LOG(ERROR) << "Could not determine major/minor for: " << cow_name; return false; } - if (paths) { - paths->cow_device = cow_device; - } remaining_time = GetRemainingTime(params.timeout_ms, begin); if (remaining_time.count() < 0) return false; - if (context == SnapshotContext::Update && IsCompressionEnabled()) { - // Stop here, we can't run dm-user yet, the COW isn't built. - return true; - } - - std::string path; if (!MapSnapshot(lock, params.GetPartitionName(), base_device, cow_device, remaining_time, - &path)) { + path)) { LOG(ERROR) << "Could not map snapshot for partition: " << params.GetPartitionName(); return false; } // No need to add params.GetPartitionName() to created_devices since it is immediately released. - if (paths) { - paths->snapshot_device = path; - } - created_devices.Release(); - LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at " << path; + LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at " << *path; + return true; } @@ -2455,86 +2438,23 @@ bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& para << params.GetPartitionName(); return false; } - - SnapshotPaths paths; - if (!MapPartitionWithSnapshot(lock.get(), params, SnapshotContext::Update, &paths)) { - return false; - } - - if (paths.snapshot_device.empty()) { - *snapshot_path = paths.snapshot_device; - } else { - *snapshot_path = paths.target_device; - } - return true; + return MapPartitionWithSnapshot(lock.get(), params, snapshot_path); } -std::unique_ptr SnapshotManager::OpenSnapshotWriter( +std::unique_ptr SnapshotManager::OpenSnapshotWriter( const android::fs_mgr::CreateLogicalPartitionParams& params) { - // First unmap any existing mapping. - auto lock = LockShared(); - if (!lock) return nullptr; - if (!UnmapPartitionWithSnapshot(lock.get(), params.GetPartitionName())) { - LOG(ERROR) << "Cannot unmap existing snapshot before re-mapping it: " - << params.GetPartitionName(); - return nullptr; - } + (void)params; - SnapshotPaths paths; - if (!MapPartitionWithSnapshot(lock.get(), params, SnapshotContext::Update, &paths)) { - return nullptr; - } - - SnapshotStatus status; - if (!paths.cow_device.empty()) { - if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) { - return nullptr; - } - } else { - // Currently, partition_cow_creator always creates snapshots. The - // reason is that if partition X shrinks while partition Y grows, we - // cannot bindly write to the newly freed extents in X. This would - // make the old slot unusable. So, the entire size of the target - // partition is currently considered snapshottable. - LOG(ERROR) << "No snapshot available for partition " << params.GetPartitionName(); - return nullptr; - } - - if (IsCompressionEnabled()) { - return OpenCompressedSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); - } else { - return OpenKernelSnapshotWriter(lock.get(), params.GetPartitionName(), status, paths); - } -} - -std::unique_ptr SnapshotManager::OpenCompressedSnapshotWriter( - LockedFile*, const std::string&, const SnapshotStatus&, const SnapshotPaths&) { - LOG(ERROR) << "OpenSnapshotWriter not yet implemented for compression"; + LOG(ERROR) << "OpenSnapshotWriter not yet implemented"; return nullptr; } -std::unique_ptr SnapshotManager::OpenKernelSnapshotWriter( - LockedFile* lock, [[maybe_unused]] const std::string& partition_name, - const SnapshotStatus& status, const SnapshotPaths& paths) { - CHECK(lock); +std::unique_ptr SnapshotManager::OpenSnapshotReader( + const android::fs_mgr::CreateLogicalPartitionParams& params) { + (void)params; - CowOptions cow_options; - cow_options.max_blocks = {status.device_size() / cow_options.block_size}; - - auto writer = std::make_unique(cow_options); - - std::string_view path = - paths.snapshot_device.empty() ? paths.target_device : paths.snapshot_device; - unique_fd fd(open(path.data(), O_RDWR | O_CLOEXEC)); - if (fd < 0) { - PLOG(ERROR) << "open failed: " << path; - return nullptr; - } - - uint64_t cow_size = status.cow_partition_size() + status.cow_file_size(); - writer->SetSnapshotDevice(std::move(fd), cow_size); - - return writer; + LOG(ERROR) << "OpenSnapshotReader not yet implemented"; + return nullptr; } bool SnapshotManager::UnmapUpdateSnapshot(const std::string& target_partition_name) { diff --git a/fs_mgr/libsnapshot/snapshot_reader.cpp b/fs_mgr/libsnapshot/snapshot_reader.cpp deleted file mode 100644 index 0d47468ae..000000000 --- a/fs_mgr/libsnapshot/snapshot_reader.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// Copyright (C) 2020 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. -// - -#include - -#include "snapshot_reader.h" - -namespace android { -namespace snapshot { - -// Not supported. -bool ReadOnlyFileDescriptor::Open(const char*, int, mode_t) { - errno = EINVAL; - return false; -} - -bool ReadOnlyFileDescriptor::Open(const char*, int) { - errno = EINVAL; - return false; -} - -ssize_t ReadOnlyFileDescriptor::Write(const void*, size_t) { - errno = EINVAL; - return false; -} - -bool ReadOnlyFileDescriptor::BlkIoctl(int, uint64_t, uint64_t, int*) { - errno = EINVAL; - return false; -} - -ReadFdFileDescriptor::ReadFdFileDescriptor(android::base::unique_fd&& fd) : fd_(std::move(fd)) {} - -ssize_t ReadFdFileDescriptor::Read(void* buf, size_t count) { - return read(fd_.get(), buf, count); -} - -off64_t ReadFdFileDescriptor::Seek(off64_t offset, int whence) { - return lseek(fd_.get(), offset, whence); -} - -uint64_t ReadFdFileDescriptor::BlockDevSize() { - return get_block_device_size(fd_.get()); -} - -bool ReadFdFileDescriptor::Close() { - fd_ = {}; - return true; -} - -bool ReadFdFileDescriptor::IsSettingErrno() { - return true; -} - -bool ReadFdFileDescriptor::IsOpen() { - return fd_ >= 0; -} - -bool ReadFdFileDescriptor::Flush() { - return true; -} - -} // namespace snapshot -} // namespace android diff --git a/fs_mgr/libsnapshot/snapshot_reader.h b/fs_mgr/libsnapshot/snapshot_reader.h deleted file mode 100644 index 1f2ffe211..000000000 --- a/fs_mgr/libsnapshot/snapshot_reader.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (C) 2020 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 -#include - -namespace android { -namespace snapshot { - -class ReadOnlyFileDescriptor : public chromeos_update_engine::FileDescriptor { - public: - bool Open(const char* path, int flags, mode_t mode) override; - bool Open(const char* path, int flags) override; - ssize_t Write(const void* buf, size_t count) override; - bool BlkIoctl(int request, uint64_t start, uint64_t length, int* result) override; -}; - -class ReadFdFileDescriptor : public ReadOnlyFileDescriptor { - public: - explicit ReadFdFileDescriptor(android::base::unique_fd&& fd); - - ssize_t Read(void* buf, size_t count) override; - off64_t Seek(off64_t offset, int whence) override; - uint64_t BlockDevSize() override; - bool Close() override; - bool IsSettingErrno() override; - bool IsOpen() override; - bool Flush() override; - - private: - android::base::unique_fd fd_; -}; - -} // namespace snapshot -} // namespace android diff --git a/fs_mgr/libsnapshot/snapshot_stub.cpp b/fs_mgr/libsnapshot/snapshot_stub.cpp index 41f5da4a8..8ae63054f 100644 --- a/fs_mgr/libsnapshot/snapshot_stub.cpp +++ b/fs_mgr/libsnapshot/snapshot_stub.cpp @@ -130,7 +130,13 @@ ISnapshotMergeStats* SnapshotManagerStub::GetSnapshotMergeStatsInstance() { return &snapshot_merge_stats; } -std::unique_ptr SnapshotManagerStub::OpenSnapshotWriter( +std::unique_ptr SnapshotManagerStub::OpenSnapshotWriter( + const CreateLogicalPartitionParams&) { + LOG(ERROR) << __FUNCTION__ << " should never be called."; + return nullptr; +} + +std::unique_ptr SnapshotManagerStub::OpenSnapshotReader( const CreateLogicalPartitionParams&) { LOG(ERROR) << __FUNCTION__ << " should never be called."; return nullptr; diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp index f2caaa4f3..6ff935bac 100644 --- a/fs_mgr/libsnapshot/snapshot_test.cpp +++ b/fs_mgr/libsnapshot/snapshot_test.cpp @@ -80,7 +80,6 @@ TestDeviceInfo* test_device = nullptr; std::string fake_super; void MountMetadata(); -bool IsCompressionEnabled(); class SnapshotTest : public ::testing::Test { public: @@ -893,39 +892,42 @@ class SnapshotUpdateTest : public SnapshotTest { return AssertionSuccess(); } - AssertionResult MapUpdateSnapshot(const std::string& name, - std::unique_ptr* writer = nullptr) { - CreateLogicalPartitionParams params{ - .block_device = fake_super, - .metadata_slot = 1, - .partition_name = name, - .timeout_ms = 10s, - .partition_opener = opener_.get(), - }; - - auto result = sm->OpenSnapshotWriter(params); - if (!result) { - return AssertionFailure() << "Cannot open snapshot for writing: " << name; + AssertionResult MapUpdateSnapshot(const std::string& name, std::string* path = nullptr) { + std::string real_path; + if (!sm->MapUpdateSnapshot( + CreateLogicalPartitionParams{ + .block_device = fake_super, + .metadata_slot = 1, + .partition_name = name, + .timeout_ms = 10s, + .partition_opener = opener_.get(), + }, + &real_path)) { + return AssertionFailure() << "Unable to map snapshot " << name; } - - if (writer) { - *writer = std::move(result); + if (path) { + *path = real_path; } - return AssertionSuccess(); + return AssertionSuccess() << "Mapped snapshot " << name << " to " << real_path; } - AssertionResult WriteSnapshotAndHash(const std::string& name) { - std::unique_ptr writer; - auto res = MapUpdateSnapshot(name, &writer); + AssertionResult WriteSnapshotAndHash(const std::string& name, + std::optional size = std::nullopt) { + std::string path; + auto res = MapUpdateSnapshot(name, &path); if (!res) { return res; } - if (!WriteRandomData(writer.get(), &hashes_[name])) { - return AssertionFailure() << "Unable to write random data to snapshot " << name; + std::string size_string = size ? (std::to_string(*size) + " bytes") : ""; + + if (!WriteRandomData(path, size, &hashes_[name])) { + return AssertionFailure() << "Unable to write " << size_string << " to " << path + << " for partition " << name; } - return AssertionSuccess() << "Written random data to snapshot " << name + return AssertionSuccess() << "Written " << size_string << " to " << path + << " for snapshot partition " << name << ", hash: " << hashes_[name]; } @@ -1001,7 +1003,7 @@ TEST_F(SnapshotUpdateTest, FullUpdateFlow) { // Write some data to target partitions. for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) { - ASSERT_TRUE(WriteSnapshotAndHash(name)); + ASSERT_TRUE(WriteSnapshotAndHash(name, partition_size)); } // Assert that source partitions aren't affected. @@ -1404,10 +1406,6 @@ void MountMetadata() { MetadataMountedTest().TearDown(); } -bool IsCompressionEnabled() { - return android::base::GetBoolProperty("ro.virtual_ab.compression.enabled", false); -} - TEST_F(MetadataMountedTest, Android) { auto device = sm->EnsureMetadataMounted(); EXPECT_NE(nullptr, device); @@ -1625,7 +1623,7 @@ TEST_F(SnapshotUpdateTest, Hashtree) { // Map and write some data to target partition. ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"})); - ASSERT_TRUE(WriteSnapshotAndHash("sys_b")); + ASSERT_TRUE(WriteSnapshotAndHash("sys_b", partition_size)); // Finish update. ASSERT_TRUE(sm->FinishedSnapshotWrites(false)); @@ -1657,7 +1655,7 @@ TEST_F(SnapshotUpdateTest, Overflow) { // Map and write some data to target partitions. ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"})); - ASSERT_TRUE(WriteSnapshotAndHash("sys_b")); + ASSERT_TRUE(WriteSnapshotAndHash("sys_b", actual_write_size)); std::vector table; ASSERT_TRUE(DeviceMapper::Instance().GetTableStatus("sys_b", &table)); diff --git a/fs_mgr/libsnapshot/snapshot_writer.cpp b/fs_mgr/libsnapshot/snapshot_writer.cpp deleted file mode 100644 index 584f15e78..000000000 --- a/fs_mgr/libsnapshot/snapshot_writer.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright (C) 2020 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. -// - -#include - -#include -#include -#include -#include "snapshot_reader.h" - -namespace android { -namespace snapshot { - -using android::base::unique_fd; -using chromeos_update_engine::FileDescriptor; - -ISnapshotWriter::ISnapshotWriter(const CowOptions& options) : ICowWriter(options) {} - -void ISnapshotWriter::SetSourceDevice(android::base::unique_fd&& source_fd) { - source_fd_ = std::move(source_fd); -} - -OnlineKernelSnapshotWriter::OnlineKernelSnapshotWriter(const CowOptions& options) - : ISnapshotWriter(options) {} - -void OnlineKernelSnapshotWriter::SetSnapshotDevice(android::base::unique_fd&& snapshot_fd, - uint64_t cow_size) { - snapshot_fd_ = std::move(snapshot_fd); - cow_size_ = cow_size; -} - -bool OnlineKernelSnapshotWriter::Flush() { - if (fsync(snapshot_fd_.get()) < 0) { - PLOG(ERROR) << "fsync"; - return false; - } - return true; -} - -bool OnlineKernelSnapshotWriter::EmitRawBlocks(uint64_t new_block_start, const void* data, - size_t size) { - uint64_t offset = new_block_start * options_.block_size; - if (lseek(snapshot_fd_.get(), offset, SEEK_SET) < 0) { - PLOG(ERROR) << "EmitRawBlocks lseek to offset " << offset; - return false; - } - if (!android::base::WriteFully(snapshot_fd_, data, size)) { - PLOG(ERROR) << "EmitRawBlocks write"; - return false; - } - return true; -} - -bool OnlineKernelSnapshotWriter::EmitZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) { - std::string zeroes(options_.block_size, 0); - for (uint64_t i = 0; i < num_blocks; i++) { - if (!EmitRawBlocks(new_block_start + i, zeroes.data(), zeroes.size())) { - return false; - } - } - return true; -} - -bool OnlineKernelSnapshotWriter::EmitCopy(uint64_t new_block, uint64_t old_block) { - std::string buffer(options_.block_size, 0); - uint64_t offset = old_block * options_.block_size; - if (!android::base::ReadFullyAtOffset(source_fd_, buffer.data(), buffer.size(), offset)) { - PLOG(ERROR) << "EmitCopy read"; - return false; - } - return EmitRawBlocks(new_block, buffer.data(), buffer.size()); -} - -std::unique_ptr OnlineKernelSnapshotWriter::OpenReader() { - unique_fd fd(dup(snapshot_fd_.get())); - if (fd < 0) { - PLOG(ERROR) << "dup2 failed in OpenReader"; - return nullptr; - } - return std::make_unique(std::move(fd)); -} - -} // namespace snapshot -} // namespace android diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp index 6104c8243..b07bf9182 100644 --- a/fs_mgr/libsnapshot/test_helpers.cpp +++ b/fs_mgr/libsnapshot/test_helpers.cpp @@ -127,48 +127,6 @@ bool WriteRandomData(const std::string& path, std::optional expect_size, return true; } -bool WriteRandomData(ICowWriter* writer, std::string* hash) { - unique_fd rand(open("/dev/urandom", O_RDONLY)); - if (rand < 0) { - PLOG(ERROR) << "open /dev/urandom"; - return false; - } - - SHA256_CTX ctx; - if (hash) { - SHA256_Init(&ctx); - } - - if (!writer->options().max_blocks) { - LOG(ERROR) << "CowWriter must specify maximum number of blocks"; - return false; - } - uint64_t num_blocks = writer->options().max_blocks.value(); - - size_t block_size = writer->options().block_size; - std::string block(block_size, '\0'); - for (uint64_t i = 0; i < num_blocks; i++) { - if (!ReadFully(rand, block.data(), block.size())) { - PLOG(ERROR) << "read /dev/urandom"; - return false; - } - if (!writer->AddRawBlocks(i, block.data(), block.size())) { - LOG(ERROR) << "Failed to add raw block " << i; - return false; - } - if (hash) { - SHA256_Update(&ctx, block.data(), block.size()); - } - } - - if (hash) { - uint8_t out[32]; - SHA256_Final(out, &ctx); - *hash = ToHexString(out, sizeof(out)); - } - return true; -} - std::optional GetHash(const std::string& path) { std::string content; if (!android::base::ReadFileToString(path, &content, true)) { diff --git a/init/Android.bp b/init/Android.bp index c3dd7f6c6..3f2cd0714 100644 --- a/init/Android.bp +++ b/init/Android.bp @@ -129,7 +129,6 @@ cc_defaults { "libprotobuf-cpp-lite", "libpropertyinfoserializer", "libpropertyinfoparser", - "libsnapshot_cow", "libsnapshot_init", "libxml2", "lib_apex_manifest_proto_lite", diff --git a/init/Android.mk b/init/Android.mk index 998e0fd46..da94daf44 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -112,7 +112,6 @@ LOCAL_STATIC_LIBRARIES := \ libmodprobe \ libext2_uuid \ libprotobuf-cpp-lite \ - libsnapshot_cow \ libsnapshot_init \ update_metadata-protos \