From 7596f4b76a31d16b01ed733be9c52ecfffa7b21a Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 21 Oct 2016 11:38:44 +0800 Subject: [PATCH] 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 --- src/mds/CDir.cc | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) 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 -- 2.47.3