From: Yan, Zheng Date: Fri, 28 Apr 2017 10:08:51 +0000 (+0800) Subject: mds: don't finish dentry waiters when splitting/merging dirfrags X-Git-Tag: v12.1.0~10^2~28^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b52b090968dc58a22a21a03c9327d83119635a47;p=ceph.git mds: don't finish dentry waiters when splitting/merging dirfrags move dentry waiters to the new dirfrags instead Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index 3bc939b43cf2..86ba961be1bb 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -869,12 +869,19 @@ void CDir::steal_dentry(CDentry *dn) dn->dir = this; } -void CDir::prepare_old_fragment(bool replay) +void CDir::prepare_old_fragment(map >& dentry_waiters, bool replay) { // auth_pin old fragment for duration so that any auth_pinning // during the dentry migration doesn't trigger side effects if (!replay && is_auth()) auth_pin(this); + + if (!waiting_on_dentry.empty()) { + for (auto p = waiting_on_dentry.begin(); p != waiting_on_dentry.end(); ++p) + dentry_waiters[p->first].swap(p->second); + waiting_on_dentry.clear(); + put(PIN_DNWAITER); + } } void CDir::prepare_new_fragment(bool replay) @@ -960,7 +967,8 @@ void CDir::split(int bits, list& subs, list& wai fragstatdiff.add_delta(fnode.accounted_fragstat, fnode.fragstat); dout(10) << " rstatdiff " << rstatdiff << " fragstatdiff " << fragstatdiff << dendl; - prepare_old_fragment(replay); + map > dentry_waiters; + prepare_old_fragment(dentry_waiters, replay); // create subfrag dirs int n = 0; @@ -1004,6 +1012,16 @@ void CDir::split(int bits, list& subs, list& wai f->steal_dentry(dn); } + for (auto& p : dentry_waiters) { + frag_t subfrag = inode->pick_dirfrag(p.first.name); + int n = (subfrag.value() & (subfrag.mask() ^ frag.mask())) >> subfrag.mask_shift(); + CDir *f = subfrags[n]; + + if (f->waiting_on_dentry.empty()) + f->get(PIN_DNWAITER); + f->waiting_on_dentry[p.first].swap(p.second); + } + // FIXME: handle dirty old rstat // fix up new frag fragstats @@ -1048,6 +1066,8 @@ void CDir::merge(list& subs, list& waiters, bool version_t rstat_version = inode->get_projected_inode()->rstat.version; version_t dirstat_version = inode->get_projected_inode()->dirstat.version; + map > dentry_waiters; + for (auto dir : subs) { dout(10) << " subfrag " << dir->get_frag() << " " << *dir << dendl; assert(!dir->is_auth() || dir->is_complete() || replay); @@ -1058,7 +1078,7 @@ void CDir::merge(list& subs, list& waiters, bool fragstatdiff.add_delta(dir->fnode.accounted_fragstat, dir->fnode.fragstat, &touched_mtime, &touched_chattr); - dir->prepare_old_fragment(replay); + dir->prepare_old_fragment(dentry_waiters, replay); // steal dentries while (!dir->items.empty()) @@ -1085,6 +1105,13 @@ void CDir::merge(list& subs, list& waiters, bool inode->close_dirfrag(dir->get_frag()); } + if (!dentry_waiters.empty()) { + get(PIN_DNWAITER); + for (auto& p : dentry_waiters) { + waiting_on_dentry[p.first].swap(p.second); + } + } + if (is_auth() && !replay) mark_complete(); diff --git a/src/mds/CDir.h b/src/mds/CDir.h index 4c90292df33b..5b0079a74de4 100644 --- a/src/mds/CDir.h +++ b/src/mds/CDir.h @@ -483,7 +483,7 @@ public: private: void prepare_new_fragment(bool replay); - void prepare_old_fragment(bool replay); + void prepare_old_fragment(map >& dentry_waiters, bool replay); void steal_dentry(CDentry *dn); // from another dir. used by merge/split. void finish_old_fragment(list& waiters, bool replay); void init_fragment_pins(); diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index a407a8769d9b..9a0208014bec 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -10101,10 +10101,11 @@ void MDCache::handle_discover_reply(MDiscoverReply *m) if (who >= 0) dout(7) << " dir_auth_hint is " << m->get_dir_auth_hint() << dendl; - frag_t fg = m->get_base_dir_frag(); - CDir *dir = cur->get_dirfrag(fg); if (m->get_wanted_base_dir()) { + frag_t fg = m->get_base_dir_frag(); + CDir *dir = cur->get_dirfrag(fg); + if (cur->is_waiting_for_dir(fg)) { if (cur->is_auth()) cur->take_waiting(CInode::WAIT_DIR, finished); @@ -10118,6 +10119,8 @@ void MDCache::handle_discover_reply(MDiscoverReply *m) // try again? if (m->get_error_dentry().length()) { + frag_t fg = cur->pick_dirfrag(m->get_error_dentry()); + CDir *dir = cur->get_dirfrag(fg); // wanted a dentry if (dir && dir->is_waiting_for_dentry(m->get_error_dentry(), m->get_wanted_snapid())) { if (dir->is_auth() || dir->lookup(m->get_error_dentry())) {