Loading fs_mgr/libsnapshot/cow_snapuserd_test.cpp +20 −17 Original line number Diff line number Diff line Loading @@ -108,6 +108,8 @@ class SnapuserdTest : public ::testing::Test { std::unique_ptr<uint8_t[]> product_buffer_; void Init(); void InitCowDevices(); void InitDaemon(); void CreateCowDevice(std::unique_ptr<TemporaryFile>& cow); void CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow); void CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow); Loading Loading @@ -238,12 +240,6 @@ void SnapuserdTest::CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow) { system_device_name_.clear(); system_device_ctrl_name_.clear(); // Create a COW device. Number of sectors is chosen random which can // hold at least 400MB of data int err = ioctl(sys_fd_.get(), BLKGETSIZE, &system_blksize_); ASSERT_GE(err, 0); std::string str(cow->path); std::size_t found = str.find_last_of("/\\"); ASSERT_NE(found, std::string::npos); Loading Loading @@ -280,12 +276,6 @@ void SnapuserdTest::CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow) { product_device_name_.clear(); product_device_ctrl_name_.clear(); // Create a COW device. Number of sectors is chosen random which can // hold at least 400MB of data int err = ioctl(product_fd_.get(), BLKGETSIZE, &product_blksize_); ASSERT_GE(err, 0); std::string str(cow->path); std::size_t found = str.find_last_of("/\\"); ASSERT_NE(found, std::string::npos); Loading @@ -297,12 +287,15 @@ void SnapuserdTest::CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow) { system(cmd.c_str()); } void SnapuserdTest::StartSnapuserdDaemon() { ASSERT_TRUE(EnsureSnapuserdStarted()); void SnapuserdTest::InitCowDevices() { system_blksize_ = client_->InitDmUserCow(cow_system_->path); ASSERT_NE(system_blksize_, 0); client_ = SnapuserdClient::Connect(kSnapuserdSocket, 5s); ASSERT_NE(client_, nullptr); product_blksize_ = client_->InitDmUserCow(cow_product_->path); ASSERT_NE(product_blksize_, 0); } void SnapuserdTest::InitDaemon() { bool ok = client_->InitializeSnapuserd(cow_system_->path, system_a_loop_->device(), GetSystemControlPath()); ASSERT_TRUE(ok); Loading @@ -312,6 +305,13 @@ void SnapuserdTest::StartSnapuserdDaemon() { ASSERT_TRUE(ok); } void SnapuserdTest::StartSnapuserdDaemon() { ASSERT_TRUE(EnsureSnapuserdStarted()); client_ = SnapuserdClient::Connect(kSnapuserdSocket, 5s); ASSERT_NE(client_, nullptr); } void SnapuserdTest::CreateSnapshotDevices() { std::string cmd; Loading Loading @@ -435,10 +435,13 @@ TEST_F(SnapuserdTest, ReadWrite) { CreateCowDevice(cow_system_); CreateCowDevice(cow_product_); StartSnapuserdDaemon(); InitCowDevices(); CreateSystemDmUser(cow_system_); CreateProductDmUser(cow_product_); StartSnapuserdDaemon(); InitDaemon(); CreateSnapshotDevices(); Loading fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h +9 −10 Original line number Diff line number Diff line Loading @@ -61,23 +61,19 @@ class BufferSink : public IByteSink { class Snapuserd final { public: Snapuserd(const std::string& in_cow_device, const std::string& in_backing_store_device, const std::string& in_control_device) : cow_device_(in_cow_device), backing_store_device_(in_backing_store_device), control_device_(in_control_device), metadata_read_done_(false) {} bool Init(); bool InitBackingAndControlDevice(std::string& backing_device, std::string& control_device); bool InitCowDevice(std::string& cow_device); int Run(); const std::string& GetControlDevicePath() { return control_device_; } const std::string& GetCowDevice() { return cow_device_; } uint64_t GetNumSectors() { return num_sectors_; } private: int ReadDmUserHeader(); bool ReadDmUserPayload(void* buffer, size_t size); int WriteDmUserPayload(size_t size); int ConstructKernelCowHeader(); int ReadMetadata(); bool ReadMetadata(); int ZerofillDiskExceptions(size_t read_size); int ReadDiskExceptions(chunk_t chunk, size_t size); int ReadData(chunk_t chunk, size_t size); Loading @@ -94,6 +90,8 @@ class Snapuserd final { int unmerged_exceptions); bool AdvanceMergedOps(int merged_ops_cur_iter); bool ProcessMergeComplete(chunk_t chunk, void* buffer); sector_t ChunkToSector(chunk_t chunk) { return chunk << CHUNK_SHIFT; } chunk_t SectorToChunk(sector_t sector) { return sector >> CHUNK_SHIFT; } std::string cow_device_; std::string backing_store_device_; Loading @@ -104,6 +102,7 @@ class Snapuserd final { unique_fd ctrl_fd_; uint32_t exceptions_per_area_; uint64_t num_sectors_; std::unique_ptr<ICowOpIter> cowop_iter_; std::unique_ptr<ICowOpReverseIter> cowop_riter_; Loading @@ -118,7 +117,7 @@ class Snapuserd final { // Value - cow operation std::unordered_map<chunk_t, const CowOperation*> chunk_map_; bool metadata_read_done_; bool metadata_read_done_ = false; BufferSink bufsink_; }; Loading fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h +1 −1 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ class SnapuserdClient { std::chrono::milliseconds timeout_ms); bool StopSnapuserd(); int RestartSnapuserd(std::vector<std::vector<std::string>>& vec); uint64_t InitDmUserCow(const std::string& cow_device); bool InitializeSnapuserd(const std::string& cow_device, const std::string& backing_device, const std::string& control_device); Loading fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ namespace snapshot { static constexpr uint32_t MAX_PACKET_SIZE = 512; enum class DaemonOperations { INIT, START, QUERY, STOP, Loading fs_mgr/libsnapshot/snapshot.cpp +19 −22 Original line number Diff line number Diff line Loading @@ -386,24 +386,6 @@ bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name, auto& dm = DeviceMapper::Instance(); // Use the size of the base device for the COW device. It doesn't really // matter, it just needs to look similar enough so the kernel doesn't complain // about alignment or being too small. uint64_t base_sectors = 0; { unique_fd fd(open(base_device.c_str(), O_RDONLY | O_CLOEXEC)); if (fd < 0) { PLOG(ERROR) << "open failed: " << base_device; return false; } auto dev_size = get_block_device_size(fd); if (!dev_size) { PLOG(ERROR) << "Could not determine block device size: " << base_device; return false; } base_sectors = dev_size / kSectorSize; } // Use an extra decoration for first-stage init, so we can transition // to a new table entry in second-stage. std::string misc_name = name; Loading @@ -411,13 +393,19 @@ bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name, misc_name += "-init"; } DmTable table; table.Emplace<DmTargetUser>(0, base_sectors, misc_name); if (!dm.CreateDevice(name, table, path, timeout_ms)) { if (!EnsureSnapuserdConnected()) { return false; } if (!EnsureSnapuserdConnected()) { uint64_t base_sectors = snapuserd_client_->InitDmUserCow(cow_file); if (base_sectors == 0) { LOG(ERROR) << "Failed to retrieve base_sectors from Snapuserd"; return false; } DmTable table; table.Emplace<DmTargetUser>(0, base_sectors, misc_name); if (!dm.CreateDevice(name, table, path, timeout_ms)) { return false; } Loading Loading @@ -1366,6 +1354,15 @@ bool SnapshotManager::PerformSecondStageTransition() { continue; } uint64_t base_sectors = snapuserd_client_->InitDmUserCow(cow_device); if (base_sectors == 0) { // Unrecoverable as metadata reads from cow device failed LOG(FATAL) << "Failed to retrieve base_sectors from Snapuserd"; return false; } CHECK(base_sectors == target.spec.length); if (!snapuserd_client_->InitializeSnapuserd(cow_device, backing_device, control_device)) { // This error is unrecoverable. We cannot proceed because reads to // the underlying device will fail. Loading Loading
fs_mgr/libsnapshot/cow_snapuserd_test.cpp +20 −17 Original line number Diff line number Diff line Loading @@ -108,6 +108,8 @@ class SnapuserdTest : public ::testing::Test { std::unique_ptr<uint8_t[]> product_buffer_; void Init(); void InitCowDevices(); void InitDaemon(); void CreateCowDevice(std::unique_ptr<TemporaryFile>& cow); void CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow); void CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow); Loading Loading @@ -238,12 +240,6 @@ void SnapuserdTest::CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow) { system_device_name_.clear(); system_device_ctrl_name_.clear(); // Create a COW device. Number of sectors is chosen random which can // hold at least 400MB of data int err = ioctl(sys_fd_.get(), BLKGETSIZE, &system_blksize_); ASSERT_GE(err, 0); std::string str(cow->path); std::size_t found = str.find_last_of("/\\"); ASSERT_NE(found, std::string::npos); Loading Loading @@ -280,12 +276,6 @@ void SnapuserdTest::CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow) { product_device_name_.clear(); product_device_ctrl_name_.clear(); // Create a COW device. Number of sectors is chosen random which can // hold at least 400MB of data int err = ioctl(product_fd_.get(), BLKGETSIZE, &product_blksize_); ASSERT_GE(err, 0); std::string str(cow->path); std::size_t found = str.find_last_of("/\\"); ASSERT_NE(found, std::string::npos); Loading @@ -297,12 +287,15 @@ void SnapuserdTest::CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow) { system(cmd.c_str()); } void SnapuserdTest::StartSnapuserdDaemon() { ASSERT_TRUE(EnsureSnapuserdStarted()); void SnapuserdTest::InitCowDevices() { system_blksize_ = client_->InitDmUserCow(cow_system_->path); ASSERT_NE(system_blksize_, 0); client_ = SnapuserdClient::Connect(kSnapuserdSocket, 5s); ASSERT_NE(client_, nullptr); product_blksize_ = client_->InitDmUserCow(cow_product_->path); ASSERT_NE(product_blksize_, 0); } void SnapuserdTest::InitDaemon() { bool ok = client_->InitializeSnapuserd(cow_system_->path, system_a_loop_->device(), GetSystemControlPath()); ASSERT_TRUE(ok); Loading @@ -312,6 +305,13 @@ void SnapuserdTest::StartSnapuserdDaemon() { ASSERT_TRUE(ok); } void SnapuserdTest::StartSnapuserdDaemon() { ASSERT_TRUE(EnsureSnapuserdStarted()); client_ = SnapuserdClient::Connect(kSnapuserdSocket, 5s); ASSERT_NE(client_, nullptr); } void SnapuserdTest::CreateSnapshotDevices() { std::string cmd; Loading Loading @@ -435,10 +435,13 @@ TEST_F(SnapuserdTest, ReadWrite) { CreateCowDevice(cow_system_); CreateCowDevice(cow_product_); StartSnapuserdDaemon(); InitCowDevices(); CreateSystemDmUser(cow_system_); CreateProductDmUser(cow_product_); StartSnapuserdDaemon(); InitDaemon(); CreateSnapshotDevices(); Loading
fs_mgr/libsnapshot/include/libsnapshot/snapuserd.h +9 −10 Original line number Diff line number Diff line Loading @@ -61,23 +61,19 @@ class BufferSink : public IByteSink { class Snapuserd final { public: Snapuserd(const std::string& in_cow_device, const std::string& in_backing_store_device, const std::string& in_control_device) : cow_device_(in_cow_device), backing_store_device_(in_backing_store_device), control_device_(in_control_device), metadata_read_done_(false) {} bool Init(); bool InitBackingAndControlDevice(std::string& backing_device, std::string& control_device); bool InitCowDevice(std::string& cow_device); int Run(); const std::string& GetControlDevicePath() { return control_device_; } const std::string& GetCowDevice() { return cow_device_; } uint64_t GetNumSectors() { return num_sectors_; } private: int ReadDmUserHeader(); bool ReadDmUserPayload(void* buffer, size_t size); int WriteDmUserPayload(size_t size); int ConstructKernelCowHeader(); int ReadMetadata(); bool ReadMetadata(); int ZerofillDiskExceptions(size_t read_size); int ReadDiskExceptions(chunk_t chunk, size_t size); int ReadData(chunk_t chunk, size_t size); Loading @@ -94,6 +90,8 @@ class Snapuserd final { int unmerged_exceptions); bool AdvanceMergedOps(int merged_ops_cur_iter); bool ProcessMergeComplete(chunk_t chunk, void* buffer); sector_t ChunkToSector(chunk_t chunk) { return chunk << CHUNK_SHIFT; } chunk_t SectorToChunk(sector_t sector) { return sector >> CHUNK_SHIFT; } std::string cow_device_; std::string backing_store_device_; Loading @@ -104,6 +102,7 @@ class Snapuserd final { unique_fd ctrl_fd_; uint32_t exceptions_per_area_; uint64_t num_sectors_; std::unique_ptr<ICowOpIter> cowop_iter_; std::unique_ptr<ICowOpReverseIter> cowop_riter_; Loading @@ -118,7 +117,7 @@ class Snapuserd final { // Value - cow operation std::unordered_map<chunk_t, const CowOperation*> chunk_map_; bool metadata_read_done_; bool metadata_read_done_ = false; BufferSink bufsink_; }; Loading
fs_mgr/libsnapshot/include/libsnapshot/snapuserd_client.h +1 −1 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ class SnapuserdClient { std::chrono::milliseconds timeout_ms); bool StopSnapuserd(); int RestartSnapuserd(std::vector<std::vector<std::string>>& vec); uint64_t InitDmUserCow(const std::string& cow_device); bool InitializeSnapuserd(const std::string& cow_device, const std::string& backing_device, const std::string& control_device); Loading
fs_mgr/libsnapshot/include/libsnapshot/snapuserd_server.h +1 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ namespace snapshot { static constexpr uint32_t MAX_PACKET_SIZE = 512; enum class DaemonOperations { INIT, START, QUERY, STOP, Loading
fs_mgr/libsnapshot/snapshot.cpp +19 −22 Original line number Diff line number Diff line Loading @@ -386,24 +386,6 @@ bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name, auto& dm = DeviceMapper::Instance(); // Use the size of the base device for the COW device. It doesn't really // matter, it just needs to look similar enough so the kernel doesn't complain // about alignment or being too small. uint64_t base_sectors = 0; { unique_fd fd(open(base_device.c_str(), O_RDONLY | O_CLOEXEC)); if (fd < 0) { PLOG(ERROR) << "open failed: " << base_device; return false; } auto dev_size = get_block_device_size(fd); if (!dev_size) { PLOG(ERROR) << "Could not determine block device size: " << base_device; return false; } base_sectors = dev_size / kSectorSize; } // Use an extra decoration for first-stage init, so we can transition // to a new table entry in second-stage. std::string misc_name = name; Loading @@ -411,13 +393,19 @@ bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name, misc_name += "-init"; } DmTable table; table.Emplace<DmTargetUser>(0, base_sectors, misc_name); if (!dm.CreateDevice(name, table, path, timeout_ms)) { if (!EnsureSnapuserdConnected()) { return false; } if (!EnsureSnapuserdConnected()) { uint64_t base_sectors = snapuserd_client_->InitDmUserCow(cow_file); if (base_sectors == 0) { LOG(ERROR) << "Failed to retrieve base_sectors from Snapuserd"; return false; } DmTable table; table.Emplace<DmTargetUser>(0, base_sectors, misc_name); if (!dm.CreateDevice(name, table, path, timeout_ms)) { return false; } Loading Loading @@ -1366,6 +1354,15 @@ bool SnapshotManager::PerformSecondStageTransition() { continue; } uint64_t base_sectors = snapuserd_client_->InitDmUserCow(cow_device); if (base_sectors == 0) { // Unrecoverable as metadata reads from cow device failed LOG(FATAL) << "Failed to retrieve base_sectors from Snapuserd"; return false; } CHECK(base_sectors == target.spec.length); if (!snapuserd_client_->InitializeSnapuserd(cow_device, backing_device, control_device)) { // This error is unrecoverable. We cannot proceed because reads to // the underlying device will fail. Loading