]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix empty directory check
authorYan, Zheng <zheng.z.yan@intel.com>
Thu, 7 Nov 2013 09:07:51 +0000 (17:07 +0800)
committerYan, Zheng <zheng.z.yan@intel.com>
Mon, 16 Dec 2013 04:15:23 +0000 (12:15 +0800)
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 <zheng.z.yan@intel.com>
src/mds/Server.cc

index ee9aae137f05c9aef1091226e0a9c5727ab676c7..1c8a34f94397a00e095bf1fa80bcafed9aa86bc7 100644 (file)
@@ -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<CDir*> ls;
+  in->get_dirfrags(ls);
+  for (list<CDir*>::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();
 }