Directory hierarchy may be deep for a large filesystem, dump loads would output
a lot and take a long time. So add an arg to limit depth when dump loads of dirfrags.
Fixes: https://tracker.ceph.com/issues/56058
Signed-off-by: haoyixing <haoyixing@kuaishou.com>
(cherry picked from commit
a8f138cd3623e42c4f74a18d54ec7dfcc1e89e58)
Conflicts:
* qa/tasks/cephfs/test_admin.py
Conflict occurred because test_admin.py on Quincy branch was updated
by PR #54946.
self.fs.mds_asok(['dump', 'tree', '~mdsdir'])
+class TestAdminCommandDumpLoads(CephFSTestCase):
+ """
+ Tests for administration command dump loads.
+ """
+
+ CLIENTS_REQUIRED = 0
+ MDSS_REQUIRED = 1
+
+ def test_dump_loads(self):
+ """
+ make sure depth limit param is considered when dump loads for a MDS daemon.
+ """
+
+ log.info("dumping loads")
+ loads = self.fs.mds_asok(['dump', 'loads', '1'])
+ self.assertIsNotNone(loads)
+ self.assertIn("dirfrags", loads)
+ for d in loads["dirfrags"]:
+ self.assertLessEqual(d["path"].count("/"), 1)
+
+
class TestPermErrMsg(CephFSTestCase):
CLIENT_NAME = 'client.testuser'
}
}
-int MDBalancer::dump_loads(Formatter *f) const
+int MDBalancer::dump_loads(Formatter *f, int64_t depth) const
{
- std::deque<CDir*> dfs;
+ std::deque<pair<CDir*, int>> dfs;
+ std::deque<CDir*> dfs_root;
if (mds->mdcache->get_root()) {
- mds->mdcache->get_root()->get_dirfrags(dfs);
+ mds->mdcache->get_root()->get_dirfrags(dfs_root);
+ while (!dfs_root.empty()) {
+ CDir *dir = dfs_root.front();
+ dfs_root.pop_front();
+ dfs.push_back(make_pair(dir, 0));
+ }
} else {
dout(10) << "no root" << dendl;
}
f->open_array_section("dirfrags");
while (!dfs.empty()) {
- CDir *dir = dfs.front();
+ auto [dir, cur_depth] = dfs.front();
dfs.pop_front();
f->open_object_section("dir");
dir->dump_load(f);
f->close_section();
+ //limit output dirfrags depth
+ if (depth >= 0 && (cur_depth + 1) > depth) {
+ continue;
+ }
+
for (auto it = dir->begin(); it != dir->end(); ++it) {
CInode *in = it->second->get_linkage()->get_inode();
if (!in || !in->is_dir())
auto&& ls = in->get_dirfrags();
for (const auto& subdir : ls) {
+
if (subdir->pop_nested.meta_load() < .001)
continue;
- dfs.push_back(subdir);
+ dfs.push_back(make_pair(subdir, cur_depth+1));
}
}
}
void handle_mds_failure(mds_rank_t who);
- int dump_loads(Formatter *f) const;
+ int dump_loads(Formatter *f, int64_t depth = -1) const;
private:
typedef struct {
asok_hook,
"dump metadata cache for subtree");
ceph_assert(r == 0);
- r = admin_socket->register_command("dump loads",
+ r = admin_socket->register_command("dump loads "
+ "name=depth,type=CephInt,range=0,req=false",
asok_hook,
"dump metadata loads");
ceph_assert(r == 0);
command_dump_tree(cmdmap, *css, f);
} else if (command == "dump loads") {
std::lock_guard l(mds_lock);
- r = balancer->dump_loads(f);
+ int64_t depth = -1;
+ bool got = cmd_getval(cmdmap, "depth", depth);
+ if (!got || depth < 0) {
+ dout(10) << "no depth limit when dirfrags dump_load" << dendl;
+ }
+ r = balancer->dump_loads(f, depth);
} else if (command == "dump snaps") {
std::lock_guard l(mds_lock);
string server;