From 56548b2eab18c66b4ab1d15e934cf0fe5ab6e155 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 7 Mar 2011 16:25:30 -0800 Subject: [PATCH] mds: use projected subtree in rename anchor check 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 --- src/mds/CDir.cc | 2 +- src/mds/CInode.cc | 7 +++++++ src/mds/CInode.h | 1 + src/mds/MDCache.cc | 12 ++++++++++++ src/mds/MDCache.h | 1 + src/mds/Server.cc | 2 +- 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index e19f91d78895a..96fa8fad26da9 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -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()) { diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 311d1d64f53b3..49fe113762384 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -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) diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 3c79245320d20..acb67dd93d8f9 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -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 { diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 6d4fa4d79f110..46d6d390a5bfd 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -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; diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index b1d557a7d886a..2c198bc2ec2b7 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -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(); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index d006fba1ccba4..38dca7e44c602 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -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 trace; -- 2.39.5