]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: use projected subtree in rename anchor check
authorSage Weil <sage@newdream.net>
Tue, 8 Mar 2011 00:25:30 +0000 (16:25 -0800)
committerSage Weil <sage@newdream.net>
Tue, 8 Mar 2011 00:26:34 +0000 (16:26 -0800)
We want to (try to) reanchor the directory on rename when our _projected_
subtree is not a leaf.  If we use the normal get_subtree_root() call,
we get NULL if we are unlinked, which makes is_leaf_subtree() crash.

Signed-off-by: Sage Weil <sage.weil@dreamhost.com>
src/mds/CDir.cc
src/mds/CInode.cc
src/mds/CInode.h
src/mds/MDCache.cc
src/mds/MDCache.h
src/mds/Server.cc

index e19f91d78895a4005a49751f7552df4dc1c08e97..96fa8fad26da9bc95d2ee2fd9dea39c18d245562 100644 (file)
@@ -49,7 +49,7 @@ boost::pool<> CDir::pool(sizeof(CDir));
 ostream& operator<<(ostream& out, CDir& dir)
 {
   string path;
-  dir.get_inode()->make_path_string(path);
+  dir.get_inode()->make_path_string_projected(path);
   out << "[dir " << dir.dirfrag() << " " << path << "/"
       << " [" << dir.first << ",head]";
   if (dir.is_auth()) {
index 311d1d64f53b3147291ba42363422ad3e3223a7b..49fe113762384670e6cb4ca364afa23c9fc32b15 100644 (file)
@@ -685,6 +685,13 @@ CDir *CInode::get_parent_dir()
     return parent->dir;
   return NULL;
 }
+CDir *CInode::get_projected_parent_dir()
+{
+  CDentry *p = get_projected_parent_dn();
+  if (p)
+    return p->dir;
+  return NULL;
+}
 CInode *CInode::get_parent_inode() 
 {
   if (parent) 
index 3c79245320d2088c9ac87b8f25ed1e138f90d981..acb67dd93d8f915121957e19bd1047cd500888fe 100644 (file)
@@ -525,6 +525,7 @@ private:
   CDentry* get_parent_dn() { return parent; }
   CDentry* get_projected_parent_dn() { return projected_parent.size() ? projected_parent.back():parent; }
   CDir *get_parent_dir();
+  CDir *get_projected_parent_dir();
   CInode *get_parent_inode();
   
   bool is_lt(const MDSCacheObject *r) const {
index 6d4fa4d79f110cba1d277f30753c9e4d986d5068..46d6d390a5bfd8aee916b03e170dc5ddf31a20ad 100644 (file)
@@ -1096,6 +1096,18 @@ CDir *MDCache::get_subtree_root(CDir *dir)
   }
 }
 
+CDir *MDCache::get_projected_subtree_root(CDir *dir)
+{
+  // find the underlying dir that delegates (or is about to delegate) auth
+  while (true) {
+    if (dir->is_subtree_root()) 
+      return dir;
+    dir = dir->get_inode()->get_projected_parent_dir();
+    if (!dir) 
+      return 0;             // none
+  }
+}
+
 void MDCache::remove_subtree(CDir *dir)
 {
   dout(10) << "remove_subtree " << *dir << dendl;
index b1d557a7d886a71ec118ee46150c870a0cc9f92d..2c198bc2ec2b713eafb7e8c701bf89a0524d70de 100644 (file)
@@ -550,6 +550,7 @@ public:
   void subtree_merge_writebehind_finish(CInode *in, Mutation *mut);
   void eval_subtree_root(CInode *diri);
   CDir *get_subtree_root(CDir *dir);
+  CDir *get_projected_subtree_root(CDir *dir);
   bool is_leaf_subtree(CDir *dir) {
     assert(subtrees.count(dir));
     return subtrees[dir].empty();
index d006fba1ccba430daf9f983d466275fa9975fc85..38dca7e44c6024360c098afc153b3e6e39131fb5 100644 (file)
@@ -4718,7 +4718,7 @@ void Server::handle_client_rename(MDRequest *mdr)
       (srcdnl->get_inode()->is_anchored() || 
        (srcdnl->get_inode()->is_dir() && (srcdnl->get_inode()->inode.rstat.ranchors ||
                                          srcdnl->get_inode()->nested_anchors ||
-                                         !mdcache->is_leaf_subtree(mdcache->get_subtree_root(srcdn->get_dir()))))) &&
+                                         !mdcache->is_leaf_subtree(mdcache->get_projected_subtree_root(srcdn->get_dir()))))) &&
       !mdr->more()->src_reanchor_atid) {
     dout(10) << "reanchoring src->dst " << *srcdnl->get_inode() << dendl;
     vector<Anchor> trace;