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)
* 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;
}
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() ||
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;
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));