From: Yan, Zheng Date: Sun, 22 Jan 2017 02:24:28 +0000 (+0800) Subject: mds: don't modify inode that is not projected X-Git-Tag: v12.0.0~73^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fb0bb07b2f49be69aacc73aca99ef4d03f0da8c2;p=ceph.git mds: don't modify inode that is not projected In the slave rename prep case (rename inode to different auth mds), the rename inode is not projected. CDir::check_rstat() gets confused if MDCache::_project_rstat_inode_to_frag() updates inode's accounted rstat in that case. Fixes: http://tracker.ceph.com/issues/16768 Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 136c72c1e14..6331915017e 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -1770,8 +1770,18 @@ void MDCache::project_rstat_inode_to_frag(CInode *cur, CDir *parent, snapid_t fi return; } - if (cur->last >= floor) - _project_rstat_inode_to_frag(*curi, MAX(first, floor), cur->last, parent, linkunlink); + if (cur->last >= floor) { + bool update = true; + if (cur->state_test(CInode::STATE_AMBIGUOUSAUTH) && cur->is_auth()) { + // rename src inode is not projected in the slave rename prep case. so we should + // avoid updateing the inode. + assert(linkunlink < 0); + assert(cur->is_frozen_inode()); + update = false; + } + _project_rstat_inode_to_frag(*curi, MAX(first, floor), cur->last, parent, + linkunlink, update); + } if (g_conf->mds_snap_rstat) { for (compact_set::iterator p = cur->dirty_old_rstats.begin(); @@ -1783,7 +1793,7 @@ void MDCache::project_rstat_inode_to_frag(CInode *cur, CDir *parent, snapid_t fi if (q == snaps.end() || *q > *p) continue; if (*p >= floor) - _project_rstat_inode_to_frag(old.inode, ofirst, *p, parent, 0); + _project_rstat_inode_to_frag(old.inode, ofirst, *p, parent, 0, false); } } cur->dirty_old_rstats.clear(); @@ -1791,7 +1801,7 @@ void MDCache::project_rstat_inode_to_frag(CInode *cur, CDir *parent, snapid_t fi void MDCache::_project_rstat_inode_to_frag(inode_t& inode, snapid_t ofirst, snapid_t last, - CDir *parent, int linkunlink) + CDir *parent, int linkunlink, bool update_inode) { dout(10) << "_project_rstat_inode_to_frag [" << ofirst << "," << last << "]" << dendl; dout(20) << " inode rstat " << inode.rstat << dendl; @@ -1807,7 +1817,8 @@ void MDCache::_project_rstat_inode_to_frag(inode_t& inode, snapid_t ofirst, snap } dout(20) << " delta " << delta << dendl; - inode.accounted_rstat = inode.rstat; + if (update_inode) + inode.accounted_rstat = inode.rstat; while (last >= ofirst) { /* @@ -1900,7 +1911,8 @@ void MDCache::_project_rstat_inode_to_frag(inode_t& inode, snapid_t ofirst, snap dout(20) << " project to [" << first << "," << last << "] " << *prstat << dendl; assert(last >= first); prstat->add(delta); - inode.accounted_rstat = inode.rstat; + if (update_inode) + inode.accounted_rstat = inode.rstat; dout(20) << " result [" << first << "," << last << "] " << *prstat << " " << *parent << dendl; last = first-1; diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index a9c41193478..e328f441ae6 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -350,7 +350,7 @@ public: void project_rstat_inode_to_frag(CInode *cur, CDir *parent, snapid_t first, int linkunlink, SnapRealm *prealm); void _project_rstat_inode_to_frag(inode_t& inode, snapid_t ofirst, snapid_t last, - CDir *parent, int linkunlink=0); + CDir *parent, int linkunlink, bool update_inode); void project_rstat_frag_to_inode(nest_info_t& rstat, nest_info_t& accounted_rstat, snapid_t ofirst, snapid_t last, CInode *pin, bool cow_head); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 5bdf3a41b08..e9983101c51 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -7723,7 +7723,7 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t master, MDRequestRef if (srcdn && srcdn->authority().first == whoami) { nest_info_t blah; _rollback_repair_dir(mut, srcdir, rollback.orig_src, rollback.ctime, - in ? in->is_dir() : false, 1, pi ? pi->rstat : blah); + in ? in->is_dir() : false, 1, pi ? pi->accounted_rstat : blah); } // repair dest