From: Yan, Zheng Date: Fri, 21 Oct 2016 03:38:44 +0000 (+0800) Subject: mds: fix CDir::log_mark_dirty() X-Git-Tag: v11.1.0~522^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F11560%2Fhead;p=ceph.git mds: fix CDir::log_mark_dirty() CDir::log_mark_dirty() moves dirfrag to current log segment's dirty dirfrag list, but it does not submit any log event. Old log segments (that include events which dirty the dirfrag) may get expired before the dirfrag gets committed. If MDS crashes, the changes in expired log segments get lost. Signed-off-by: Yan, Zheng --- diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index 7d101ce44b73..6e719da3532b 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -1357,24 +1357,14 @@ void CDir::mark_clean() } } - -struct C_Dir_Dirty : public CDirContext { - version_t pv; - LogSegment *ls; - C_Dir_Dirty(CDir *d, version_t p, LogSegment *l) : CDirContext(d), pv(p), ls(l) {} - void finish(int r) { - dir->mark_dirty(pv, ls); - dir->auth_unpin(dir); - } -}; - // caller should hold auth pin of this void CDir::log_mark_dirty() { - MDLog *mdlog = inode->mdcache->mds->mdlog; + if (is_dirty() || is_projected()) + return; // noop if it is already dirty or will be dirty + version_t pv = pre_dirty(); - mdlog->flush(); - mdlog->wait_for_safe(new C_Dir_Dirty(this, pv, mdlog->get_current_segment())); + mark_dirty(pv, cache->mds->mdlog->get_current_segment()); } void CDir::mark_complete() { @@ -1878,10 +1868,10 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map& omap, } // dirty myself to remove stale snap dentries - if (force_dirty && !is_dirty() && !inode->mdcache->is_readonly()) + if (force_dirty && !inode->mdcache->is_readonly()) log_mark_dirty(); - else - auth_unpin(this); + + auth_unpin(this); if (complete) { // kick waiters