Skip to content

Commit 801951e

Browse files
committed
mds: implement new asok command for dumping stray folder
Signed-off-by: Igor Golikov <[email protected]> Fixes: https://tracker.ceph.com/issues/56442
1 parent df404e0 commit 801951e

File tree

4 files changed

+97
-13
lines changed

4 files changed

+97
-13
lines changed

src/mds/MDCache.cc

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10211,13 +10211,21 @@ void MDCache::notify_global_snaprealm_update(int snap_op)
1021110211

1021210212
struct C_MDC_RetryScanStray : public MDCacheContext {
1021310213
dirfrag_t next;
10214-
C_MDC_RetryScanStray(MDCache *c, dirfrag_t n) : MDCacheContext(c), next(n) { }
10214+
std::unique_ptr<MDCache::C_MDS_DumpStrayDirCtx> cmd_ctx;
10215+
C_MDC_RetryScanStray(MDCache *c, dirfrag_t n, std::unique_ptr<MDCache::C_MDS_DumpStrayDirCtx> ctx) :
10216+
MDCacheContext(c), next(n), cmd_ctx(std::move(ctx)) {}
1021510217
void finish(int r) override {
10216-
mdcache->scan_stray_dir(next);
10218+
mdcache->scan_stray_dir(next, std::move(cmd_ctx));
1021710219
}
1021810220
};
1021910221

10220-
void MDCache::scan_stray_dir(dirfrag_t next)
10222+
/*
10223+
* If the cmd_ctx is not nullptr, the caller is asok command handler,
10224+
* which will block until the on_finish will be called.
10225+
* The cmd_ctx holds the formatter to dump stray dir content while scanning.
10226+
* The function can return EAGAIN, to make possible waiting semantics clear.
10227+
*/
10228+
int MDCache::scan_stray_dir(dirfrag_t next, std::unique_ptr<MDCache::C_MDS_DumpStrayDirCtx> cmd_ctx)
1022110229
{
1022210230
dout(10) << "scan_stray_dir " << next << dendl;
1022310231

@@ -10236,13 +10244,13 @@ void MDCache::scan_stray_dir(dirfrag_t next)
1023610244
continue;
1023710245

1023810246
if (!dir->can_auth_pin()) {
10239-
dir->add_waiter(CDir::WAIT_UNFREEZE, new C_MDC_RetryScanStray(this, dir->dirfrag()));
10240-
return;
10247+
dir->add_waiter(CDir::WAIT_UNFREEZE, new C_MDC_RetryScanStray(this, dir->dirfrag(), std::move(cmd_ctx)));
10248+
return -EAGAIN;
1024110249
}
1024210250

1024310251
if (!dir->is_complete()) {
10244-
dir->fetch(new C_MDC_RetryScanStray(this, dir->dirfrag()));
10245-
return;
10252+
dir->fetch(new C_MDC_RetryScanStray(this, dir->dirfrag(), std::move(cmd_ctx)));
10253+
return -EAGAIN;
1024610254
}
1024710255

1024810256
for (auto &p : dir->items) {
@@ -10251,14 +10259,32 @@ void MDCache::scan_stray_dir(dirfrag_t next)
1025110259
CDentry::linkage_t *dnl = dn->get_projected_linkage();
1025210260
if (dnl->is_primary()) {
1025310261
CInode *in = dnl->get_inode();
10262+
// only if we came from asok cmd handler
10263+
if (cmd_ctx) {
10264+
cmd_ctx->begin_dump();
10265+
cmd_ctx->get_formatter()->open_object_section("stray_inode");
10266+
cmd_ctx->get_formatter()->dump_int("ino: ", in->ino());
10267+
cmd_ctx->get_formatter()->dump_string("stray_prior_path: ", in->get_inode()->stray_prior_path);
10268+
in->dump(cmd_ctx->get_formatter(), CInode::DUMP_CAPS);
10269+
cmd_ctx->get_formatter()->close_section();
10270+
}
1025410271
if (in->get_inode()->nlink == 0)
1025510272
in->state_set(CInode::STATE_ORPHAN);
10256-
maybe_eval_stray(in);
10273+
// no need to evaluate stray when dumping the dir content
10274+
if (!cmd_ctx) {
10275+
maybe_eval_stray(in);
10276+
}
1025710277
}
1025810278
}
1025910279
}
1026010280
next.frag = frag_t();
1026110281
}
10282+
// only if we came from asok cmd handler
10283+
if (cmd_ctx) {
10284+
cmd_ctx->end_dump();
10285+
cmd_ctx->finish(0);
10286+
}
10287+
return 0;
1026210288
}
1026310289

1026410290
void MDCache::fetch_backtrace(inodeno_t ino, int64_t pool, bufferlist& bl, Context *fin)
@@ -10269,9 +10295,10 @@ void MDCache::fetch_backtrace(inodeno_t ino, int64_t pool, bufferlist& bl, Conte
1026910295
mds->logger->inc(l_mds_openino_backtrace_fetch);
1027010296
}
1027110297

10272-
10273-
10274-
10298+
int MDCache::stray_status(std::unique_ptr<C_MDS_DumpStrayDirCtx> ctx)
10299+
{
10300+
return scan_stray_dir(dirfrag_t(), std::move(ctx));
10301+
}
1027510302

1027610303
// ========================================================================================
1027710304
// DISCOVER

src/mds/MDCache.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,40 @@ class MDCache {
641641
bool ap_freeze = false;
642642
};
643643

644+
/**
645+
* Helper wrapper, provides both context object with finish function
646+
* and placeholder for formatter. Better alternative to passing formatter as another argument
647+
* to the MDSCache function
648+
*/
649+
class C_MDS_DumpStrayDirCtx : public MDSInternalContext {
650+
public:
651+
void finish(int r) override {
652+
ceph_assert(on_finish);
653+
MDSContext::finish(r);
654+
on_finish(r);
655+
}
656+
Formatter* get_formatter() const {
657+
ceph_assert(dump_formatter);
658+
return dump_formatter;
659+
}
660+
void begin_dump() {
661+
if(!started) {
662+
started = true;
663+
get_formatter()->open_array_section("strays");
664+
}
665+
}
666+
void end_dump() {
667+
get_formatter()->close_section();
668+
}
669+
C_MDS_DumpStrayDirCtx(MDCache *c, Formatter* f, std::function<void(int)>&& ext_on_finish) :
670+
MDSInternalContext(c->mds), cache(c), dump_formatter(f), on_finish(std::move(ext_on_finish)) {}
671+
private:
672+
MDCache *cache;
673+
Formatter* dump_formatter;
674+
std::function<void(int)> on_finish;
675+
bool started = false;
676+
};
677+
644678
MDRequestRef lock_path(LockPathConfig config, std::function<void(MDRequestRef const& mdr)> on_locked = {});
645679

646680
void clean_open_file_lists();
@@ -1072,6 +1106,7 @@ class MDCache {
10721106
void dump_tree(CInode *in, const int cur_depth, const int max_depth, Formatter *f);
10731107

10741108
void cache_status(Formatter *f);
1109+
int stray_status(std::unique_ptr<C_MDS_DumpStrayDirCtx> ctx);
10751110

10761111
void dump_resolve_status(Formatter *f) const;
10771112
void dump_rejoin_status(Formatter *f) const;
@@ -1271,7 +1306,7 @@ class MDCache {
12711306
void handle_open_ino(const cref_t<MMDSOpenIno> &m, int err=0);
12721307
void handle_open_ino_reply(const cref_t<MMDSOpenInoReply> &m);
12731308

1274-
void scan_stray_dir(dirfrag_t next=dirfrag_t());
1309+
int scan_stray_dir(dirfrag_t next=dirfrag_t(), std::unique_ptr<C_MDS_DumpStrayDirCtx> ctx = nullptr);
12751310
// -- replicas --
12761311
void handle_discover(const cref_t<MDiscover> &dis);
12771312
void handle_discover_reply(const cref_t<MDiscoverReply> &m);

src/mds/MDSDaemon.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,11 @@ void MDSDaemon::set_up_admin_socket()
544544
asok_hook,
545545
"run cpu profiling on daemon");
546546
ceph_assert(r == 0);
547+
r = admin_socket->register_command(
548+
"dump stray",
549+
asok_hook,
550+
"dump stray folder content");
551+
ceph_assert(r == 0);
547552
}
548553

549554
void MDSDaemon::clean_up_admin_socket()

src/mds/MDSRank.cc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3070,6 +3070,23 @@ void MDSRankDispatcher::handle_asok_command(
30703070
} else if (command == "quiesce db") {
30713071
command_quiesce_db(cmdmap, on_finish);
30723072
return;
3073+
} else if (command == "dump stray") {
3074+
dout(10) << "dump_stray start" << dendl;
3075+
// the context is a wrapper for formatter to be used while scanning stray dir
3076+
auto context = std::make_unique<MDCache::C_MDS_DumpStrayDirCtx>(mdcache, f,
3077+
[this,on_finish](int r) {
3078+
// completion callback, will be called when scan is done
3079+
dout(10) << "dump_stray done" << dendl;
3080+
bufferlist bl;
3081+
on_finish(r, "", bl);
3082+
});
3083+
std::lock_guard l(mds_lock);
3084+
r = mdcache->stray_status(std::move(context));
3085+
// since the scanning op can be async, we want to know it, for better semantics
3086+
if (r == -EAGAIN) {
3087+
dout(10) << "dump_stray wait" << dendl;
3088+
}
3089+
return;
30733090
} else {
30743091
r = -ENOSYS;
30753092
}
@@ -3506,7 +3523,7 @@ void MDSRank::command_quiesce_path(Formatter* f, const cmdmap_t& cmdmap, asok_fi
35063523

35073524
// This is a little ugly, apologies.
35083525
// We should still be under the mds lock for this test to be valid.
3509-
// MDCache will delete the quiesce_ctx if it manages to complete syncrhonously,
3526+
// MDCache will delete the quiesce_ctx if it manages
35103527
// so we are testing the `mdr->internal_op_finish` to see if that has happend
35113528
if (!await && mdr && mdr->internal_op_finish) {
35123529
ceph_assert(mdr->internal_op_finish == quiesce_ctx);

0 commit comments

Comments
 (0)