From: Yan, Zheng Date: Fri, 14 Apr 2017 01:28:10 +0000 (+0800) Subject: mds: use 'is in stray' instead 'nlink == 0' to check deleted inodes X-Git-Tag: v12.1.0~10^2~28^2~11 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=00fdbd89c0a44ee965615ed3992ed3801506baa9;p=ceph.git mds: use 'is in stray' instead 'nlink == 0' to check deleted inodes Checking inode's nlink is not reliable when mds is not auth mds of the inode. This patch also removes the code that skips committing dirfrag of deleted inode. it's not safe for uncommitted slave rmmdir. Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index eb813c9a7e06..3bc939b43cf2 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -712,7 +712,7 @@ void CDir::remove_null_dentries() { void CDir::try_remove_dentries_for_stray() { dout(10) << __func__ << dendl; - assert(inode->inode.nlink == 0); + assert(get_parent_dir()->inode->is_stray()); // clear dirty only when the directory was not snapshotted bool clear_dirty = !inode->snaprealm; @@ -1445,9 +1445,11 @@ void CDir::fetch(MDSInternalContextBase *c, const string& want_dn, bool ignore_a } // unlinked directory inode shouldn't have any entry - if (inode->inode.nlink == 0 && !inode->snaprealm) { + if (!inode->is_base() && get_parent_dir()->inode->is_stray() && + !inode->snaprealm) { dout(7) << "fetch dirfrag for unlinked directory, mark complete" << dendl; if (get_version() == 0) { + assert(inode->is_auth()); set_version(1); if (state_test(STATE_REJOINUNDEF)) { @@ -2023,14 +2025,6 @@ void CDir::commit(version_t want, MDSInternalContextBase *c, bool ignore_authpin assert(is_auth()); assert(ignore_authpinnability || can_auth_pin()); - if (inode->inode.nlink == 0 && !inode->snaprealm) { - dout(7) << "commit dirfrag for unlinked directory, mark clean" << dendl; - try_remove_dentries_for_stray(); - if (c) - cache->mds->queue_waiter(c); - return; - } - // note: queue up a noop if necessary, so that we always // get an auth_pin. if (!c) @@ -2288,9 +2282,10 @@ void CDir::_committed(int r, version_t v) if (r < 0) { // the directory could be partly purged during MDS failover if (r == -ENOENT && committed_version == 0 && - inode->inode.nlink == 0 && inode->snaprealm) { - inode->state_set(CInode::STATE_MISSINGOBJS); + !inode->is_base() && get_parent_dir()->inode->is_stray()) { r = 0; + if (inode->snaprealm) + inode->state_set(CInode::STATE_MISSINGOBJS); } if (r < 0) { dout(1) << "commit error " << r << " v " << v << dendl; @@ -2381,7 +2376,8 @@ void CDir::_committed(int r, version_t v) } // try drop dentries in this dirfrag if it's about to be purged - if (inode->inode.nlink == 0 && inode->snaprealm) + if (!inode->is_base() && get_parent_dir()->inode->is_stray() && + inode->snaprealm) cache->maybe_eval_stray(inode, true); // unpin if we kicked the last waiter.