From: Yan, Zheng Date: Fri, 14 Apr 2017 12:22:39 +0000 (+0800) Subject: mds: fix stray creation/removal notification X-Git-Tag: v12.0.2~13^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F14554%2Fhead;p=ceph.git mds: fix stray creation/removal notification In MDCache::scan_stray_dir(), notify_stray_created() is called for both null and non-null dentries. This is wrong, it should be called only for non-null dentries. Calling notify_stray_created() in MDCache::get_or_create_stray_dentry() is racy too. MDS can create wrong stray dentry because target dentry linkage can change before rmdir/rename lock the dentry lock. Fixes: http://tracker.ceph.com/issues/19630 Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/CDentry.cc b/src/mds/CDentry.cc index 032f83a4297a..8790377858ea 100644 --- a/src/mds/CDentry.cc +++ b/src/mds/CDentry.cc @@ -249,6 +249,18 @@ void CDentry::unlink_remote(CDentry::linkage_t *dnl) dnl->inode = 0; } +void CDentry::push_projected_linkage() +{ + _project_linkage(); + + if (is_auth()) { + CInode *diri = dir->inode; + if (diri->is_stray()) + diri->mdcache->notify_stray_removed(); + } +} + + void CDentry::push_projected_linkage(CInode *inode) { // dirty rstat tracking is in the projected plane @@ -261,6 +273,12 @@ void CDentry::push_projected_linkage(CInode *inode) if (dirty_rstat) inode->mark_dirty_rstat(); + + if (is_auth()) { + CInode *diri = dir->inode; + if (diri->is_stray()) + diri->mdcache->notify_stray_created(); + } } CDentry::linkage_t *CDentry::pop_projected_linkage() diff --git a/src/mds/CDentry.h b/src/mds/CDentry.h index 3d300237f6a7..f9505875e046 100644 --- a/src/mds/CDentry.h +++ b/src/mds/CDentry.h @@ -168,9 +168,7 @@ public: projected.push_back(linkage_t()); return &projected.back(); } - void push_projected_linkage() { - _project_linkage(); - } + void push_projected_linkage(); void push_projected_linkage(inodeno_t ino, char d_type) { linkage_t *p = _project_linkage(); p->remote_ino = ino; diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 88832279d2fd..3fea6e416c24 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -657,6 +657,7 @@ void MDCache::populate_mydir() } // open or create stray + uint64_t num_strays = 0; for (int i = 0; i < NUM_STRAY; ++i) { stringstream name; name << "stray" << i; @@ -699,9 +700,14 @@ void MDCache::populate_mydir() dir->fetch(new C_MDS_RetryOpenRoot(this)); return; } + + if (dir->get_frag_size() > 0) + num_strays += dir->get_frag_size(); } } + stray_manager.set_num_strays(num_strays); + // okay! dout(10) << "populate_mydir done" << dendl; assert(!open); @@ -742,11 +748,6 @@ CDentry *MDCache::get_or_create_stray_dentry(CInode *in) assert(straydn->get_projected_linkage()->is_null()); } - // Notify even if a null dentry already existed, because - // StrayManager counts the number of stray inodes, not the - // number of dentries in the directory. - stray_manager.notify_stray_created(); - straydn->state_set(CDentry::STATE_STRAY); return straydn; } @@ -9389,7 +9390,6 @@ void MDCache::scan_stray_dir(dirfrag_t next) for (CDir::map_t::iterator q = dir->items.begin(); q != dir->items.end(); ++q) { CDentry *dn = q->second; dn->state_set(CDentry::STATE_STRAY); - stray_manager.notify_stray_created(); CDentry::linkage_t *dnl = dn->get_projected_linkage(); if (dnl->is_primary()) { CInode *in = dnl->get_inode(); @@ -12276,6 +12276,21 @@ void MDCache::register_perfcounters() stray_manager.set_logger(logger.get()); } +void MDCache::activate_stray_manager() +{ + if (open) { + stray_manager.activate(); + } else { + wait_for_open( + new MDSInternalContextWrapper(mds, + new FunctionContext([this](int r){ + stray_manager.activate(); + }) + ) + ); + } +} + /** * Call this when putting references to an inode/dentry or * when attempting to trim it. diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index 76e779794a74..cd0afbe9d090 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -142,9 +142,7 @@ public: stray_index = (stray_index+1)%NUM_STRAY; } - void activate_stray_manager() { - stray_manager.activate(); - } + void activate_stray_manager(); /** * Call this when you know that a CDentry is ready to be passed diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 9cf926bce4b9..12a677daf645 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -7116,20 +7116,6 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C } } - if (srcdn->get_dir()->inode->is_stray() && - srcdn->get_dir()->inode->get_stray_owner() == mds->get_nodeid()) { - // A reintegration event or a migration away from me - dout(20) << __func__ << ": src dentry was a stray, updating stats" << dendl; - mdcache->notify_stray_removed(); - } - - if (destdn->get_dir()->inode->is_stray() && - destdn->get_dir()->inode->get_stray_owner() == mds->get_nodeid()) { - // A stray migration (to me) - dout(20) << __func__ << ": dst dentry was a stray, updating stats" << dendl; - mdcache->notify_stray_created(); - } - // src if (srcdn->is_auth()) srcdn->mark_dirty(mdr->more()->pvmap[srcdn], mdr->ls); diff --git a/src/mds/StrayManager.cc b/src/mds/StrayManager.cc index 816f9249883c..f4d3ac4efc7f 100644 --- a/src/mds/StrayManager.cc +++ b/src/mds/StrayManager.cc @@ -226,7 +226,6 @@ void StrayManager::_purge_stray_purged( mds->mdlog->submit_entry(le, new C_PurgeStrayLogged(this, dn, pdv, mds->mdlog->get_current_segment())); - num_strays--; logger->set(l_mdc_num_strays, num_strays); } } @@ -377,6 +376,13 @@ void StrayManager::advance_delayed() logger->set(l_mdc_num_strays_delayed, num_strays_delayed); } +void StrayManager::set_num_strays(uint64_t num) +{ + assert(!started); + num_strays = num; + logger->set(l_mdc_num_strays, num_strays); +} + void StrayManager::notify_stray_created() { num_strays++; diff --git a/src/mds/StrayManager.h b/src/mds/StrayManager.h index eff21958ddfb..a9bf3aa7840a 100644 --- a/src/mds/StrayManager.h +++ b/src/mds/StrayManager.h @@ -127,6 +127,7 @@ class StrayManager bool eval_stray(CDentry *dn, bool delay=false); + void set_num_strays(uint64_t num); uint64_t get_num_strays() const { return num_strays; } /**