Skip to content

Commit f7a3abb

Browse files
Merge pull request ceph#57980 from ceph/wip-lusov-qdb-root-ttl
mds/quiesce-db: calculate_quiesce_map: aggregate quiesce roots' TTL as `max` Reviewed-by: Patrick Donnelly <[email protected]>
2 parents 959f007 + 0fce4d7 commit f7a3abb

File tree

2 files changed

+81
-4
lines changed

2 files changed

+81
-4
lines changed

src/mds/QuiesceDbManager.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,10 +1208,11 @@ void QuiesceDbManager::calculate_quiesce_map(QuiesceMap &map)
12081208
auto ttl = get_root_ttl(set, member, db_age);
12091209
auto root_it = map.roots.try_emplace(root, QuiesceMap::RootInfo { requested, ttl }).first;
12101210

1211-
// the min below resolves conditions when members representing the same root have different state/ttl
1212-
// e.g. if at least one member is QUIESCING then the root should be QUIESCING
1211+
// the logic below resolves conditions when members representing the same root have different state/ttl
1212+
// The state should be min, e.g. QUIESCING if at least one member is QUIESCING
1213+
// The ttl should be large enough to cover all aggregated states, i.e. max
12131214
root_it->second.state = std::min(root_it->second.state, requested);
1214-
root_it->second.ttl = std::min(root_it->second.ttl, ttl);
1215+
root_it->second.ttl = std::max(root_it->second.ttl, ttl);
12151216
}
12161217
}
12171218
}

src/test/mds/TestQuiesceDb.cc

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1659,4 +1659,80 @@ TEST_F(QuiesceDbTest, AckDuringEpochMismatch)
16591659
r.set_id = "set1";
16601660
r.await = sec(10);
16611661
}));
1662-
}
1662+
}
1663+
1664+
/* ==================================== */
1665+
TEST_F(QuiesceDbTest, QuiesceRootMerge)
1666+
{
1667+
ASSERT_NO_FATAL_FAILURE(configure_cluster({ mds_gid_t(1) }));
1668+
managers.at(mds_gid_t(1))->reset_agent_callback(QUIESCING_AGENT_CB);
1669+
1670+
ASSERT_EQ(OK(), run_request([](auto& r) {
1671+
r.set_id = "set1";
1672+
r.timeout = sec(60);
1673+
r.expiration = sec(60);
1674+
r.await = sec(60);
1675+
r.include_roots({ "root1", "root2" });
1676+
}));
1677+
1678+
EXPECT_EQ(QS_QUIESCED, last_request->response.sets.at("set1").rstate.state);
1679+
auto set1_exp = last_request->response.sets.at("set1").expiration;
1680+
1681+
// reset the agent callback to SILENT so that
1682+
// our sets stay RELEASING and QUIESCING forever
1683+
managers.at(mds_gid_t(1))->reset_agent_callback(SILENT_AGENT_CB);
1684+
1685+
ASSERT_EQ(OK(), run_request([](auto& r) {
1686+
r.set_id = "set1";
1687+
r.release();
1688+
}));
1689+
1690+
EXPECT_EQ(QS_RELEASING, last_request->response.sets.at("set1").rstate.state);
1691+
1692+
ASSERT_EQ(OK(), run_request([=](auto& r) {
1693+
r.set_id = "set2";
1694+
r.timeout = set1_exp*2;
1695+
r.expiration = set1_exp*2;
1696+
r.include_roots({ "root2", "root3" });
1697+
}));
1698+
1699+
EXPECT_EQ(QS_QUIESCING, last_request->response.sets.at("set2").rstate.state);
1700+
1701+
// at this point, we should expect to have root1 RELEASING, root3 QUIESCING
1702+
// and root2, which is shared, should take the min state (QUIESCING) and the max ttl
1703+
1704+
auto agent_map = [this]() -> std::optional<QuiesceMap> {
1705+
std::promise<QuiesceMap> agent_map_promise;
1706+
auto agent_map_future = agent_map_promise.get_future();
1707+
1708+
managers.at(mds_gid_t(1))->reset_agent_callback([&agent_map_promise](QuiesceMap& map) -> bool {
1709+
try {
1710+
agent_map_promise.set_value(map);
1711+
} catch (std::future_error) {
1712+
// ignore this if we accidentally get called more than once
1713+
}
1714+
return false;
1715+
});
1716+
1717+
if (std::future_status::ready == agent_map_future.wait_for(std::chrono::seconds(10))) {
1718+
return agent_map_future.get();
1719+
}
1720+
else {
1721+
return std::nullopt;
1722+
}
1723+
}();
1724+
1725+
ASSERT_TRUE(agent_map.has_value());
1726+
EXPECT_EQ(3, agent_map->roots.size());
1727+
1728+
{
1729+
auto const & r1 = agent_map->roots.at("file:/root1");
1730+
auto const & r2 = agent_map->roots.at("file:/root2");
1731+
auto const & r3 = agent_map->roots.at("file:/root3");
1732+
1733+
EXPECT_EQ(QS_RELEASING, r1.state);
1734+
EXPECT_EQ(QS_QUIESCING, r2.state);
1735+
EXPECT_EQ(QS_QUIESCING, r3.state);
1736+
EXPECT_EQ(std::max(r1.ttl, r3.ttl), r2.ttl);
1737+
}
1738+
}

0 commit comments

Comments
 (0)