From 913f7fd8dbc0cc96de58cbc96e88394b5b952fd7 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 7 Nov 2013 17:07:51 +0800 Subject: [PATCH] mds: fix empty directory check Since commit 310032ee81(fix mds scatter_writebehind starvation), rdlock a scatter lock does not always propagate dirty fragstats to corresponding inode. So Server::_dir_is_nonempty() needs to check each dirfrag's stat intead of checking inode's dirstat. Signed-off-by: Yan, Zheng --- src/mds/Server.cc | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/mds/Server.cc b/src/mds/Server.cc index ee9aae137f05c..1c8a34f94397a 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -5315,19 +5315,29 @@ bool Server::_dir_is_nonempty(MDRequest *mdr, CInode *in) { dout(10) << "dir_is_nonempty " << *in << dendl; assert(in->is_auth()); + assert(in->filelock.can_read(-1)); - if (in->snaprealm && in->snaprealm->srnode.snaps.size()) - return true; // in a snapshot! + frag_info_t dirstat; + version_t dirstat_version = in->get_projected_inode()->dirstat.version; - if (in->get_projected_inode()->dirstat.size() > 0) { - dout(10) << "dir_is_nonempty projected dir size still " - << in->get_projected_inode()->dirstat.size() - << " on " << *in - << dendl; - return true; + list ls; + in->get_dirfrags(ls); + for (list::iterator p = ls.begin(); p != ls.end(); ++p) { + CDir *dir = *p; + fnode_t *pf = dir->get_projected_fnode(); + if (pf->fragstat.size()) { + dout(10) << "dir_is_nonempty_unlocked dirstat has " + << pf->fragstat.size() << " items " << *dir << dendl; + return true; + } + + if (pf->accounted_fragstat.version == dirstat_version) + dirstat.add(pf->accounted_fragstat); + else + dirstat.add(pf->fragstat); } - return false; + return dirstat.size() != in->get_projected_inode()->dirstat.size(); } -- 2.39.5