From: Yan, Zheng Date: Thu, 7 Nov 2013 09:07:51 +0000 (+0800) Subject: mds: fix empty directory check X-Git-Tag: v0.75~93^2~29 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=913f7fd8dbc0cc96de58cbc96e88394b5b952fd7;p=ceph.git 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 --- diff --git a/src/mds/Server.cc b/src/mds/Server.cc index ee9aae137f05..1c8a34f94397 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(); }