]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: add function MDCache::trim_non_auth_subtree
authorGreg Farnum <gregf@hq.newdream.net>
Wed, 27 Oct 2010 21:48:37 +0000 (14:48 -0700)
committerGreg Farnum <gregf@hq.newdream.net>
Fri, 29 Oct 2010 18:29:14 +0000 (11:29 -0700)
Trims the subtree rooted at the given dir from cache, except
for those portions linking to directories on other MDSes.
Meant for use during replay.

src/mds/MDCache.cc
src/mds/MDCache.h

index e9d8036452918ae9b5f8f86ee4af62018d58aff4..1f51a05346113378fa3a98f37dce80a24158eff7 100644 (file)
@@ -5164,6 +5164,71 @@ void MDCache::trim_non_auth()
   show_subtrees();
 }
 
+/**
+ * Recursively trim the subtree rooted at directory to remove all
+ * CInodes/CDentrys/CDirs that aren't links to remote MDSes, or ancestors
+ * of those links. This is used to clear invalid data out of the cache.
+ * Note that it doesn't clear the passed-in directory, since that's not
+ * always safe.
+ */
+bool MDCache::trim_non_auth_subtree(CDir *directory)
+{
+  dout(10) << "trim_non_auth_subtree " << directory << dendl;
+  bool keep_directory = false;
+  CDir::map_t::iterator j = directory->begin();
+  CDir::map_t::iterator i = j;
+  while (j != directory->end()) {
+    i = j++;
+    CDentry *dn = i->second;
+    dout(10) << "Checking dentry " << dn << dendl;
+    CDentry::linkage_t *dnl = dn->get_linkage();
+    if (dnl->is_primary()) { // check for subdirectories, etc
+      CInode *in = dnl->get_inode();
+      bool keep_inode = false;
+      if (in->is_dir()) {
+        list<CDir*> subdirs;
+        in->get_dirfrags(subdirs);
+        for (list<CDir*>::iterator subdir = subdirs.begin();
+            subdir != subdirs.end();
+            ++subdir) {
+          if ((*subdir)->is_subtree_root()) {
+            keep_inode = true;
+            dout(10) << "subdir " << *subdir << "is kept!" << dendl;
+          }
+          else {
+            if (trim_non_auth_subtree(*subdir))
+              keep_inode = true;
+            else {
+              in->close_dirfrag((*subdir)->get_frag());
+              directory->state_clear(CDir::STATE_COMPLETE);  // now incomplete!
+            }
+          }
+        }
+
+      }
+      if (!keep_inode) { // remove it!
+        dout(20) << "removing inode " << in << " with dentry" << dn << dendl;
+        directory->unlink_inode(dn);
+        remove_inode(in);
+        directory->remove_dentry(dn);
+      } else {
+        dout(20) << "keeping inode " << in << "with dentry " << dn <<dendl;
+        keep_directory = true;
+      }
+    } else { // just remove it
+      dout(20) << "removing dentry " << dn << dendl;
+      if (dnl->is_remote())
+        directory->unlink_inode(dn);
+      directory->remove_dentry(dn);
+    }
+  }
+  /**
+   * We've now checked all our children and deleted those that need it.
+   * Now return to caller, and tell them if *we're* a keeper.
+   */
+  return keep_directory;
+}
+
 /* This function DOES put the passed message before returning */
 void MDCache::handle_cache_expire(MCacheExpire *m)
 {
index 34c96c2cefa953886797bc8fce153d6ba12f25e6..1e1705591af1c778bef1ed6e737714ba221222c6 100644 (file)
@@ -829,6 +829,7 @@ public:
                  map<int,class MCacheExpire*>& expiremap);
   void send_expire_messages(map<int, MCacheExpire*>& expiremap);
   void trim_non_auth();      // trim out trimmable non-auth items
+  bool trim_non_auth_subtree(CDir *directory);
 
   void trim_client_leases();
   void check_memory_usage();