Loading fs_mgr/libsnapshot/cow_snapuserd_test.cpp +55 −3 Original line number Original line Diff line number Diff line Loading @@ -98,6 +98,7 @@ class CowSnapuserdTest final { void ValidateMerge(); void ValidateMerge(); void ReadSnapshotDeviceAndValidate(); void ReadSnapshotDeviceAndValidate(); void Shutdown(); void Shutdown(); void MergeInterrupt(); std::string snapshot_dev() const { return snapshot_dev_->path(); } std::string snapshot_dev() const { return snapshot_dev_->path(); } Loading @@ -105,7 +106,11 @@ class CowSnapuserdTest final { private: private: void SetupImpl(); void SetupImpl(); void MergeImpl(); void MergeImpl(); void SimulateDaemonRestart(); void StartMerge(); void CreateCowDevice(); void CreateCowDevice(); void CreateBaseDevice(); void CreateBaseDevice(); void InitCowDevice(); void InitCowDevice(); Loading @@ -130,7 +135,7 @@ class CowSnapuserdTest final { std::unique_ptr<uint8_t[]> merged_buffer_; std::unique_ptr<uint8_t[]> merged_buffer_; bool setup_ok_ = false; bool setup_ok_ = false; bool merge_ok_ = false; bool merge_ok_ = false; size_t size_ = 1_MiB; size_t size_ = 50_MiB; int cow_num_sectors_; int cow_num_sectors_; int total_base_size_; int total_base_size_; }; }; Loading @@ -154,9 +159,13 @@ unique_fd CowSnapuserdTest::CreateTempFile(const std::string& name, size_t size) } } void CowSnapuserdTest::Shutdown() { void CowSnapuserdTest::Shutdown() { ASSERT_TRUE(client_->StopSnapuserd()); ASSERT_TRUE(snapshot_dev_->Destroy()); ASSERT_TRUE(snapshot_dev_->Destroy()); ASSERT_TRUE(dmuser_dev_->Destroy()); ASSERT_TRUE(dmuser_dev_->Destroy()); auto misc_device = "/dev/dm-user/" + system_device_ctrl_name_; ASSERT_TRUE(client_->WaitForDeviceDelete(system_device_ctrl_name_)); ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted(misc_device, 10s)); ASSERT_TRUE(client_->DetachSnapuserd()); } } bool CowSnapuserdTest::Setup() { bool CowSnapuserdTest::Setup() { Loading Loading @@ -367,7 +376,7 @@ bool CowSnapuserdTest::Merge() { return merge_ok_; return merge_ok_; } } void CowSnapuserdTest::MergeImpl() { void CowSnapuserdTest::StartMerge() { DmTable merge_table; DmTable merge_table; ASSERT_TRUE(merge_table.AddTarget(std::make_unique<DmTargetSnapshot>( ASSERT_TRUE(merge_table.AddTarget(std::make_unique<DmTargetSnapshot>( 0, total_base_size_ / kSectorSize, base_loop_->device(), dmuser_dev_->path(), 0, total_base_size_ / kSectorSize, base_loop_->device(), dmuser_dev_->path(), Loading @@ -377,6 +386,11 @@ void CowSnapuserdTest::MergeImpl() { DeviceMapper& dm = DeviceMapper::Instance(); DeviceMapper& dm = DeviceMapper::Instance(); ASSERT_TRUE(dm.LoadTableAndActivate("cowsnapuserd-test-dm-snapshot", merge_table)); ASSERT_TRUE(dm.LoadTableAndActivate("cowsnapuserd-test-dm-snapshot", merge_table)); } void CowSnapuserdTest::MergeImpl() { StartMerge(); DeviceMapper& dm = DeviceMapper::Instance(); while (true) { while (true) { vector<DeviceMapper::TargetInfo> status; vector<DeviceMapper::TargetInfo> status; Loading Loading @@ -405,6 +419,44 @@ void CowSnapuserdTest::ValidateMerge() { ASSERT_EQ(memcmp(merged_buffer_.get(), orig_buffer_.get(), total_base_size_), 0); ASSERT_EQ(memcmp(merged_buffer_.get(), orig_buffer_.get(), total_base_size_), 0); } } void CowSnapuserdTest::SimulateDaemonRestart() { Shutdown(); SetDeviceControlName(); StartSnapuserdDaemon(); InitCowDevice(); CreateDmUserDevice(); InitDaemon(); CreateSnapshotDevice(); } void CowSnapuserdTest::MergeInterrupt() { StartMerge(); std::this_thread::sleep_for(4s); SimulateDaemonRestart(); StartMerge(); std::this_thread::sleep_for(3s); SimulateDaemonRestart(); StartMerge(); std::this_thread::sleep_for(3s); SimulateDaemonRestart(); StartMerge(); std::this_thread::sleep_for(1s); SimulateDaemonRestart(); ASSERT_TRUE(Merge()); } TEST(Snapuserd_Test, Snapshot_Merge_Resume) { CowSnapuserdTest harness; ASSERT_TRUE(harness.Setup()); harness.MergeInterrupt(); harness.ValidateMerge(); harness.Shutdown(); } TEST(Snapuserd_Test, Snapshot) { TEST(Snapuserd_Test, Snapshot) { CowSnapuserdTest harness; CowSnapuserdTest harness; ASSERT_TRUE(harness.Setup()); ASSERT_TRUE(harness.Setup()); Loading fs_mgr/libsnapshot/snapuserd.cpp +19 −12 Original line number Original line Diff line number Diff line Loading @@ -96,7 +96,7 @@ void Snapuserd::ConstructKernelCowHeader() { // it will be de-compressed. // it will be de-compressed. bool Snapuserd::ProcessReplaceOp(const CowOperation* cow_op) { bool Snapuserd::ProcessReplaceOp(const CowOperation* cow_op) { if (!reader_->ReadData(*cow_op, &bufsink_)) { if (!reader_->ReadData(*cow_op, &bufsink_)) { SNAP_LOG(ERROR) << "ReadData failed for chunk: " << cow_op->new_block; SNAP_LOG(ERROR) << "ProcessReplaceOp failed for block " << cow_op->new_block; return false; return false; } } Loading @@ -113,7 +113,8 @@ bool Snapuserd::ProcessCopyOp(const CowOperation* cow_op) { // if the successive blocks are contiguous. // if the successive blocks are contiguous. if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SIZE, if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SIZE, cow_op->source * BLOCK_SIZE)) { cow_op->source * BLOCK_SIZE)) { SNAP_LOG(ERROR) << "Copy-op failed. Read from backing store at: " << cow_op->source; SNAP_PLOG(ERROR) << "Copy-op failed. Read from backing store: " << backing_store_device_ << "at block :" << cow_op->source; return false; return false; } } Loading Loading @@ -160,7 +161,7 @@ int Snapuserd::ReadUnalignedSector(sector_t sector, size_t size, << " Aligned sector: " << it->second; << " Aligned sector: " << it->second; if (!ProcessCowOp(it->second)) { if (!ProcessCowOp(it->second)) { SNAP_LOG(ERROR) << "ReadUnalignedSector: " << sector << " failed"; SNAP_LOG(ERROR) << "ReadUnalignedSector: " << sector << " failed of size: " << size; return -1; return -1; } } Loading Loading @@ -377,16 +378,21 @@ int Snapuserd::GetNumberOfMergedOps(void* merged_buffer, void* unmerged_buffer, CHECK(cow_de->new_chunk == 0); CHECK(cow_de->new_chunk == 0); break; break; } else { } else { SNAP_LOG(ERROR) << "Error in merge operation. Found invalid metadata"; SNAP_LOG(ERROR) << "Error in merge operation. Found invalid metadata: " SNAP_LOG(ERROR) << "merged_de-old-chunk: " << merged_de->old_chunk; << " merged_de-old-chunk: " << merged_de->old_chunk SNAP_LOG(ERROR) << "merged_de-new-chunk: " << merged_de->new_chunk; << " merged_de-new-chunk: " << merged_de->new_chunk SNAP_LOG(ERROR) << "cow_de-old-chunk: " << cow_de->old_chunk; << " cow_de-old-chunk: " << cow_de->old_chunk SNAP_LOG(ERROR) << "cow_de-new-chunk: " << cow_de->new_chunk; << " cow_de-new-chunk: " << cow_de->new_chunk << " unmerged_exceptions: " << unmerged_exceptions << " merged_ops_cur_iter: " << merged_ops_cur_iter << " offset: " << offset; return -1; return -1; } } } } if (*copy_op) { if (*copy_op) { SNAP_LOG(ERROR) << "Invalid batch merge of copy ops: merged_ops_cur_iter: " << merged_ops_cur_iter; CHECK(merged_ops_cur_iter == 1); CHECK(merged_ops_cur_iter == 1); } } return merged_ops_cur_iter; return merged_ops_cur_iter; Loading Loading @@ -446,7 +452,7 @@ bool Snapuserd::ProcessMergeComplete(chunk_t chunk, void* buffer) { header.num_merge_ops += merged_ops_cur_iter; header.num_merge_ops += merged_ops_cur_iter; reader_->UpdateMergeProgress(merged_ops_cur_iter); reader_->UpdateMergeProgress(merged_ops_cur_iter); if (!writer_->CommitMerge(merged_ops_cur_iter, copy_op)) { if (!writer_->CommitMerge(merged_ops_cur_iter, copy_op)) { SNAP_LOG(ERROR) << "CommitMerge failed..."; SNAP_LOG(ERROR) << "CommitMerge failed... merged_ops_cur_iter: " << merged_ops_cur_iter; return false; return false; } } Loading Loading @@ -661,7 +667,7 @@ bool Snapuserd::ReadDmUserHeader() { bool Snapuserd::WriteDmUserPayload(size_t size) { bool Snapuserd::WriteDmUserPayload(size_t size) { if (!android::base::WriteFully(ctrl_fd_, bufsink_.GetBufPtr(), if (!android::base::WriteFully(ctrl_fd_, bufsink_.GetBufPtr(), sizeof(struct dm_user_header) + size)) { sizeof(struct dm_user_header) + size)) { SNAP_PLOG(ERROR) << "Write to dm-user failed"; SNAP_PLOG(ERROR) << "Write to dm-user failed size: " << size; return false; return false; } } Loading @@ -670,7 +676,7 @@ bool Snapuserd::WriteDmUserPayload(size_t size) { bool Snapuserd::ReadDmUserPayload(void* buffer, size_t size) { bool Snapuserd::ReadDmUserPayload(void* buffer, size_t size) { if (!android::base::ReadFully(ctrl_fd_, buffer, size)) { if (!android::base::ReadFully(ctrl_fd_, buffer, size)) { SNAP_PLOG(ERROR) << "ReadDmUserPayload failed"; SNAP_PLOG(ERROR) << "ReadDmUserPayload failed size: " << size; return false; return false; } } Loading Loading @@ -808,7 +814,8 @@ bool Snapuserd::DmuserReadRequest() { ret = ReadData(sector + num_sectors_read, read_size); ret = ReadData(sector + num_sectors_read, read_size); if (ret < 0) { if (ret < 0) { SNAP_LOG(ERROR) << "ReadData failed for chunk id: " << chunk SNAP_LOG(ERROR) << "ReadData failed for chunk id: " << chunk << "Sector: " << header->sector; << " Sector: " << (sector + num_sectors_read) << " size: " << read_size << " header-len: " << header->len; header->type = DM_USER_RESP_ERROR; header->type = DM_USER_RESP_ERROR; } else { } else { SNAP_LOG(DEBUG) << "ReadData success for chunk id: " << chunk SNAP_LOG(DEBUG) << "ReadData success for chunk id: " << chunk Loading Loading
fs_mgr/libsnapshot/cow_snapuserd_test.cpp +55 −3 Original line number Original line Diff line number Diff line Loading @@ -98,6 +98,7 @@ class CowSnapuserdTest final { void ValidateMerge(); void ValidateMerge(); void ReadSnapshotDeviceAndValidate(); void ReadSnapshotDeviceAndValidate(); void Shutdown(); void Shutdown(); void MergeInterrupt(); std::string snapshot_dev() const { return snapshot_dev_->path(); } std::string snapshot_dev() const { return snapshot_dev_->path(); } Loading @@ -105,7 +106,11 @@ class CowSnapuserdTest final { private: private: void SetupImpl(); void SetupImpl(); void MergeImpl(); void MergeImpl(); void SimulateDaemonRestart(); void StartMerge(); void CreateCowDevice(); void CreateCowDevice(); void CreateBaseDevice(); void CreateBaseDevice(); void InitCowDevice(); void InitCowDevice(); Loading @@ -130,7 +135,7 @@ class CowSnapuserdTest final { std::unique_ptr<uint8_t[]> merged_buffer_; std::unique_ptr<uint8_t[]> merged_buffer_; bool setup_ok_ = false; bool setup_ok_ = false; bool merge_ok_ = false; bool merge_ok_ = false; size_t size_ = 1_MiB; size_t size_ = 50_MiB; int cow_num_sectors_; int cow_num_sectors_; int total_base_size_; int total_base_size_; }; }; Loading @@ -154,9 +159,13 @@ unique_fd CowSnapuserdTest::CreateTempFile(const std::string& name, size_t size) } } void CowSnapuserdTest::Shutdown() { void CowSnapuserdTest::Shutdown() { ASSERT_TRUE(client_->StopSnapuserd()); ASSERT_TRUE(snapshot_dev_->Destroy()); ASSERT_TRUE(snapshot_dev_->Destroy()); ASSERT_TRUE(dmuser_dev_->Destroy()); ASSERT_TRUE(dmuser_dev_->Destroy()); auto misc_device = "/dev/dm-user/" + system_device_ctrl_name_; ASSERT_TRUE(client_->WaitForDeviceDelete(system_device_ctrl_name_)); ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted(misc_device, 10s)); ASSERT_TRUE(client_->DetachSnapuserd()); } } bool CowSnapuserdTest::Setup() { bool CowSnapuserdTest::Setup() { Loading Loading @@ -367,7 +376,7 @@ bool CowSnapuserdTest::Merge() { return merge_ok_; return merge_ok_; } } void CowSnapuserdTest::MergeImpl() { void CowSnapuserdTest::StartMerge() { DmTable merge_table; DmTable merge_table; ASSERT_TRUE(merge_table.AddTarget(std::make_unique<DmTargetSnapshot>( ASSERT_TRUE(merge_table.AddTarget(std::make_unique<DmTargetSnapshot>( 0, total_base_size_ / kSectorSize, base_loop_->device(), dmuser_dev_->path(), 0, total_base_size_ / kSectorSize, base_loop_->device(), dmuser_dev_->path(), Loading @@ -377,6 +386,11 @@ void CowSnapuserdTest::MergeImpl() { DeviceMapper& dm = DeviceMapper::Instance(); DeviceMapper& dm = DeviceMapper::Instance(); ASSERT_TRUE(dm.LoadTableAndActivate("cowsnapuserd-test-dm-snapshot", merge_table)); ASSERT_TRUE(dm.LoadTableAndActivate("cowsnapuserd-test-dm-snapshot", merge_table)); } void CowSnapuserdTest::MergeImpl() { StartMerge(); DeviceMapper& dm = DeviceMapper::Instance(); while (true) { while (true) { vector<DeviceMapper::TargetInfo> status; vector<DeviceMapper::TargetInfo> status; Loading Loading @@ -405,6 +419,44 @@ void CowSnapuserdTest::ValidateMerge() { ASSERT_EQ(memcmp(merged_buffer_.get(), orig_buffer_.get(), total_base_size_), 0); ASSERT_EQ(memcmp(merged_buffer_.get(), orig_buffer_.get(), total_base_size_), 0); } } void CowSnapuserdTest::SimulateDaemonRestart() { Shutdown(); SetDeviceControlName(); StartSnapuserdDaemon(); InitCowDevice(); CreateDmUserDevice(); InitDaemon(); CreateSnapshotDevice(); } void CowSnapuserdTest::MergeInterrupt() { StartMerge(); std::this_thread::sleep_for(4s); SimulateDaemonRestart(); StartMerge(); std::this_thread::sleep_for(3s); SimulateDaemonRestart(); StartMerge(); std::this_thread::sleep_for(3s); SimulateDaemonRestart(); StartMerge(); std::this_thread::sleep_for(1s); SimulateDaemonRestart(); ASSERT_TRUE(Merge()); } TEST(Snapuserd_Test, Snapshot_Merge_Resume) { CowSnapuserdTest harness; ASSERT_TRUE(harness.Setup()); harness.MergeInterrupt(); harness.ValidateMerge(); harness.Shutdown(); } TEST(Snapuserd_Test, Snapshot) { TEST(Snapuserd_Test, Snapshot) { CowSnapuserdTest harness; CowSnapuserdTest harness; ASSERT_TRUE(harness.Setup()); ASSERT_TRUE(harness.Setup()); Loading
fs_mgr/libsnapshot/snapuserd.cpp +19 −12 Original line number Original line Diff line number Diff line Loading @@ -96,7 +96,7 @@ void Snapuserd::ConstructKernelCowHeader() { // it will be de-compressed. // it will be de-compressed. bool Snapuserd::ProcessReplaceOp(const CowOperation* cow_op) { bool Snapuserd::ProcessReplaceOp(const CowOperation* cow_op) { if (!reader_->ReadData(*cow_op, &bufsink_)) { if (!reader_->ReadData(*cow_op, &bufsink_)) { SNAP_LOG(ERROR) << "ReadData failed for chunk: " << cow_op->new_block; SNAP_LOG(ERROR) << "ProcessReplaceOp failed for block " << cow_op->new_block; return false; return false; } } Loading @@ -113,7 +113,8 @@ bool Snapuserd::ProcessCopyOp(const CowOperation* cow_op) { // if the successive blocks are contiguous. // if the successive blocks are contiguous. if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SIZE, if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SIZE, cow_op->source * BLOCK_SIZE)) { cow_op->source * BLOCK_SIZE)) { SNAP_LOG(ERROR) << "Copy-op failed. Read from backing store at: " << cow_op->source; SNAP_PLOG(ERROR) << "Copy-op failed. Read from backing store: " << backing_store_device_ << "at block :" << cow_op->source; return false; return false; } } Loading Loading @@ -160,7 +161,7 @@ int Snapuserd::ReadUnalignedSector(sector_t sector, size_t size, << " Aligned sector: " << it->second; << " Aligned sector: " << it->second; if (!ProcessCowOp(it->second)) { if (!ProcessCowOp(it->second)) { SNAP_LOG(ERROR) << "ReadUnalignedSector: " << sector << " failed"; SNAP_LOG(ERROR) << "ReadUnalignedSector: " << sector << " failed of size: " << size; return -1; return -1; } } Loading Loading @@ -377,16 +378,21 @@ int Snapuserd::GetNumberOfMergedOps(void* merged_buffer, void* unmerged_buffer, CHECK(cow_de->new_chunk == 0); CHECK(cow_de->new_chunk == 0); break; break; } else { } else { SNAP_LOG(ERROR) << "Error in merge operation. Found invalid metadata"; SNAP_LOG(ERROR) << "Error in merge operation. Found invalid metadata: " SNAP_LOG(ERROR) << "merged_de-old-chunk: " << merged_de->old_chunk; << " merged_de-old-chunk: " << merged_de->old_chunk SNAP_LOG(ERROR) << "merged_de-new-chunk: " << merged_de->new_chunk; << " merged_de-new-chunk: " << merged_de->new_chunk SNAP_LOG(ERROR) << "cow_de-old-chunk: " << cow_de->old_chunk; << " cow_de-old-chunk: " << cow_de->old_chunk SNAP_LOG(ERROR) << "cow_de-new-chunk: " << cow_de->new_chunk; << " cow_de-new-chunk: " << cow_de->new_chunk << " unmerged_exceptions: " << unmerged_exceptions << " merged_ops_cur_iter: " << merged_ops_cur_iter << " offset: " << offset; return -1; return -1; } } } } if (*copy_op) { if (*copy_op) { SNAP_LOG(ERROR) << "Invalid batch merge of copy ops: merged_ops_cur_iter: " << merged_ops_cur_iter; CHECK(merged_ops_cur_iter == 1); CHECK(merged_ops_cur_iter == 1); } } return merged_ops_cur_iter; return merged_ops_cur_iter; Loading Loading @@ -446,7 +452,7 @@ bool Snapuserd::ProcessMergeComplete(chunk_t chunk, void* buffer) { header.num_merge_ops += merged_ops_cur_iter; header.num_merge_ops += merged_ops_cur_iter; reader_->UpdateMergeProgress(merged_ops_cur_iter); reader_->UpdateMergeProgress(merged_ops_cur_iter); if (!writer_->CommitMerge(merged_ops_cur_iter, copy_op)) { if (!writer_->CommitMerge(merged_ops_cur_iter, copy_op)) { SNAP_LOG(ERROR) << "CommitMerge failed..."; SNAP_LOG(ERROR) << "CommitMerge failed... merged_ops_cur_iter: " << merged_ops_cur_iter; return false; return false; } } Loading Loading @@ -661,7 +667,7 @@ bool Snapuserd::ReadDmUserHeader() { bool Snapuserd::WriteDmUserPayload(size_t size) { bool Snapuserd::WriteDmUserPayload(size_t size) { if (!android::base::WriteFully(ctrl_fd_, bufsink_.GetBufPtr(), if (!android::base::WriteFully(ctrl_fd_, bufsink_.GetBufPtr(), sizeof(struct dm_user_header) + size)) { sizeof(struct dm_user_header) + size)) { SNAP_PLOG(ERROR) << "Write to dm-user failed"; SNAP_PLOG(ERROR) << "Write to dm-user failed size: " << size; return false; return false; } } Loading @@ -670,7 +676,7 @@ bool Snapuserd::WriteDmUserPayload(size_t size) { bool Snapuserd::ReadDmUserPayload(void* buffer, size_t size) { bool Snapuserd::ReadDmUserPayload(void* buffer, size_t size) { if (!android::base::ReadFully(ctrl_fd_, buffer, size)) { if (!android::base::ReadFully(ctrl_fd_, buffer, size)) { SNAP_PLOG(ERROR) << "ReadDmUserPayload failed"; SNAP_PLOG(ERROR) << "ReadDmUserPayload failed size: " << size; return false; return false; } } Loading Loading @@ -808,7 +814,8 @@ bool Snapuserd::DmuserReadRequest() { ret = ReadData(sector + num_sectors_read, read_size); ret = ReadData(sector + num_sectors_read, read_size); if (ret < 0) { if (ret < 0) { SNAP_LOG(ERROR) << "ReadData failed for chunk id: " << chunk SNAP_LOG(ERROR) << "ReadData failed for chunk id: " << chunk << "Sector: " << header->sector; << " Sector: " << (sector + num_sectors_read) << " size: " << read_size << " header-len: " << header->len; header->type = DM_USER_RESP_ERROR; header->type = DM_USER_RESP_ERROR; } else { } else { SNAP_LOG(DEBUG) << "ReadData success for chunk id: " << chunk SNAP_LOG(DEBUG) << "ReadData success for chunk id: " << chunk Loading