diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp index 1a483ecaf..9152677a1 100644 --- a/fs_mgr/libdm/dm_target.cpp +++ b/fs_mgr/libdm/dm_target.cpp @@ -150,6 +150,25 @@ std::string DmTargetSnapshot::GetParameterString() const { return base_device_ + " " + cow_device_ + " " + mode + " " + std::to_string(chunk_size_); } +// Computes the percentage of complition for snapshot status. +// @sectors_initial is the number of sectors_allocated stored right before +// starting the merge. +double DmTargetSnapshot::MergePercent(const DmTargetSnapshot::Status& status, + uint64_t sectors_initial) { + uint64_t s = status.sectors_allocated; + uint64_t t = status.total_sectors; + uint64_t m = status.metadata_sectors; + uint64_t i = sectors_initial == 0 ? t : sectors_initial; + + if (t <= s || i <= s) { + return 0.0; + } + if (s == 0 || t == 0 || s <= m) { + return 100.0; + } + return 100.0 / (i - m) * (i - s); +} + bool DmTargetSnapshot::ReportsOverflow(const std::string& target_type) { DeviceMapper& dm = DeviceMapper::Instance(); DmTargetTypeInfo info; diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp index 16be0d5fc..eed21dc32 100644 --- a/fs_mgr/libdm/dm_test.cpp +++ b/fs_mgr/libdm/dm_test.cpp @@ -483,6 +483,60 @@ TEST(libdm, ParseStatusText) { EXPECT_TRUE(DmTargetSnapshot::ParseStatusText("Overflow", &status)); } +TEST(libdm, DmSnapshotMergePercent) { + DmTargetSnapshot::Status status; + + // Correct input + status.sectors_allocated = 1000; + status.total_sectors = 1000; + status.metadata_sectors = 0; + EXPECT_LE(DmTargetSnapshot::MergePercent(status), 1.0); + + status.sectors_allocated = 500; + status.total_sectors = 1000; + status.metadata_sectors = 0; + EXPECT_GE(DmTargetSnapshot::MergePercent(status), 49.0); + EXPECT_LE(DmTargetSnapshot::MergePercent(status), 51.0); + + status.sectors_allocated = 0; + status.total_sectors = 1000; + status.metadata_sectors = 0; + EXPECT_GE(DmTargetSnapshot::MergePercent(status), 99.0); + + status.sectors_allocated = 500; + status.total_sectors = 1000; + status.metadata_sectors = 500; + EXPECT_GE(DmTargetSnapshot::MergePercent(status), 99.0); + + status.sectors_allocated = 500; + status.total_sectors = 1000; + status.metadata_sectors = 0; + EXPECT_LE(DmTargetSnapshot::MergePercent(status, 500), 1.0); + EXPECT_LE(DmTargetSnapshot::MergePercent(status, 1000), 51.0); + EXPECT_GE(DmTargetSnapshot::MergePercent(status, 1000), 49.0); + + // Robustness + status.sectors_allocated = 2000; + status.total_sectors = 1000; + status.metadata_sectors = 0; + EXPECT_LE(DmTargetSnapshot::MergePercent(status), 0.0); + + status.sectors_allocated = 2000; + status.total_sectors = 1000; + status.metadata_sectors = 2000; + EXPECT_LE(DmTargetSnapshot::MergePercent(status), 0.0); + + status.sectors_allocated = 2000; + status.total_sectors = 0; + status.metadata_sectors = 2000; + EXPECT_LE(DmTargetSnapshot::MergePercent(status), 0.0); + + status.sectors_allocated = 1000; + status.total_sectors = 0; + status.metadata_sectors = 1000; + EXPECT_LE(DmTargetSnapshot::MergePercent(status, 0), 0.0); +} + TEST(libdm, CryptArgs) { DmTargetCrypt target1(0, 512, "sha1", "abcdefgh", 50, "/dev/loop0", 100); ASSERT_EQ(target1.name(), "crypt"); diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h index 722922d67..ab7c2dbbb 100644 --- a/fs_mgr/libdm/include/libdm/dm_target.h +++ b/fs_mgr/libdm/include/libdm/dm_target.h @@ -216,6 +216,7 @@ class DmTargetSnapshot final : public DmTarget { std::string error; }; + static double MergePercent(const Status& status, uint64_t sectors_initial = 0); static bool ParseStatusText(const std::string& text, Status* status); static bool ReportsOverflow(const std::string& target_type);