]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: ignore export pin for unlinked directory
authorYan, Zheng <zyan@redhat.com>
Wed, 22 Nov 2017 03:49:43 +0000 (11:49 +0800)
committerYan, Zheng <zyan@redhat.com>
Wed, 6 Dec 2017 08:49:04 +0000 (16:49 +0800)
Otherwise, stray directory inode may have pinned subtree dirfrag.
The subtree dirfrag prevents stray inode from getting purged.

Fixes: http://tracker.ceph.com/issues/22219
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
(cherry picked from commit b7cee60467582d7398bbe85e051a722e30c0897e)

src/mds/CInode.cc
src/mds/Migrator.cc
src/mds/Server.cc

index 633e6477553dda671318f2991d28dc1b2e4a621c..0184480ae847e9f5de0d54c5d5101fc619cd27c7 100644 (file)
@@ -4494,12 +4494,23 @@ mds_rank_t CInode::get_export_pin(bool inherit) const
    * N.B. inodes not yet linked into a dir (i.e. anonymous inodes) will not
    * have a parent yet.
    */
-  for (const CInode *in = this; !in->is_base() && !in->is_system() && in->get_projected_parent_dn(); in = in->get_projected_parent_dn()->dir->inode) {
-    mds_rank_t pin = in->get_projected_inode()->export_pin;
-    if (pin >= 0) {
-      return pin;
-    }
-    if (!inherit) break;
+  const CInode *in = this;
+  while (true) {
+    if (in->is_system())
+      break;
+    const CDentry *pdn = in->get_projected_parent_dn();
+    if (!pdn)
+      break;
+    const inode_t *pi = in->get_projected_inode();
+    // ignore export pin for unlinked directory
+    if (pi->nlink == 0)
+      break;
+    if (pi->export_pin >= 0)
+      return pi->export_pin;
+
+    if (!inherit)
+      break;
+    in = pdn->get_dir()->inode;
   }
   return MDS_RANK_NONE;
 }
index 6603e4f1a96662a6806214aa69509bc9b5ef723a..41fe12795139dc6bfea39233e5c0b17ba8083eff 100644 (file)
@@ -798,10 +798,17 @@ void Migrator::export_dir(CDir *dir, mds_rank_t dest)
     return;
   }
 
-  if (!dir->inode->is_base() && dir->inode->get_projected_parent_dir()->inode->is_stray() &&
-      dir->inode->get_projected_parent_dir()->get_parent_dir()->ino() != MDS_INO_MDSDIR(dest)) {
-    dout(7) << "i won't export anything in stray" << dendl;
-    return;
+  CDir* parent_dir = dir->inode->get_projected_parent_dir();
+  if (parent_dir && parent_dir->inode->is_stray()) {
+    if (parent_dir->get_parent_dir()->ino() != MDS_INO_MDSDIR(dest)) {
+      dout(7) << "i won't export anything in stray" << dendl;
+      return;
+    }
+  } else {
+    if (!mds->is_stopping() && !dir->inode->is_exportable(dest)) {
+      dout(7) << "dir is export pinned" << dendl;
+      return;
+    }
   }
 
   if (dir->is_frozen() ||
@@ -813,12 +820,6 @@ void Migrator::export_dir(CDir *dir, mds_rank_t dest)
     dout(7) << "already exporting" << dendl;
     return;
   }
-
-  if (!mds->is_stopping() && !dir->inode->is_exportable(dest)) {
-    dout(7) << "dir is export pinned" << dendl;
-    return;
-  }
-
   if (dest == mds->get_nodeid() || !mds->mdsmap->is_up(dest)) {
     dout(7) << "cannot export: dest " << dest << " is me or is not active" << dendl;
     return;
index 38c44523e95c90b8858b4bf8b4c35e90d1e3976c..06c0b1d189ef75f351c8defbaa4aa8edd4a16ab6 100644 (file)
@@ -5987,6 +5987,8 @@ void Server::_unlink_local(MDRequestRef& mdr, CDentry *dn, CDentry *straydn)
   if (in->is_dir()) {
     assert(straydn);
     mdcache->project_subtree_rename(in, dn->get_dir(), straydn->get_dir());
+
+    in->maybe_export_pin(true);
   }
 
   journal_and_reply(mdr, 0, dn, le, new C_MDS_unlink_local_finish(this, mdr, dn, straydn));