From 4d5775092d29c2eb3c2d88d1fff93ce5af4779dd Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 3 Jan 2017 11:11:12 +0800 Subject: [PATCH] mds: propagate error encountered during opening inode by number Fixes: http://tracker.ceph.com/issues/18179 Signed-off-by: Yan, Zheng (cherry picked from commit 2213cc2dcc0e8fb01bcae3863d0d8a4a1fd8873f) --- src/mds/MDCache.cc | 57 +++++++++++++++++++++++++++------------------- src/mds/MDCache.h | 9 ++++---- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index e33424afd56fe..712cc2798f9d8 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -8284,11 +8284,19 @@ class C_IO_MDC_OpenInoBacktraceFetched : public MDCacheIOContext { struct C_MDC_OpenInoTraverseDir : public MDCacheContext { inodeno_t ino; + MMDSOpenIno *msg; + bool parent; public: - C_MDC_OpenInoTraverseDir(MDCache *c, inodeno_t i) : MDCacheContext(c), ino(i) {} + C_MDC_OpenInoTraverseDir(MDCache *c, inodeno_t i, MMDSOpenIno *m, bool p) : + MDCacheContext(c), ino(i), msg(m), parent(p) {} void finish(int r) { + if (r < 0 && !parent) + r = -EAGAIN; + if (msg) { + mdcache->handle_open_ino(msg, r); + return; + } assert(mdcache->opening_inodes.count(ino)); - assert(r >= 0); mdcache->_open_ino_traverse_dir(ino, mdcache->opening_inodes[ino], r); } }; @@ -8348,6 +8356,7 @@ void MDCache::_open_ino_backtrace_fetched(inodeno_t ino, bufferlist& bl, int err new C_OnFinisher(fin, mds->finisher)); return; } + err = 0; // backtrace.ancestors.empty() is checked below } if (err == 0) { @@ -8358,11 +8367,15 @@ void MDCache::_open_ino_backtrace_fetched(inodeno_t ino, bufferlist& bl, int err if (info.ancestors[0] == backtrace.ancestors[0]) { dout(10) << " got same parents " << info.ancestors[0] << " 2 times" << dendl; err = -EINVAL; + } else { + info.last_err = 0; } } } if (err) { - dout(10) << " failed to open ino " << ino << dendl; + dout(0) << " failed to open ino " << ino << " err " << err << "/" << info.last_err << dendl; + if (info.last_err) + err = info.last_err; open_ino_finish(ino, info, err); return; } @@ -8400,14 +8413,6 @@ void MDCache::_open_ino_parent_opened(inodeno_t ino, int ret) } } -MDSInternalContextBase* MDCache::_open_ino_get_waiter(inodeno_t ino, MMDSOpenIno *m) -{ - if (m) - return new C_MDS_RetryMessage(mds, m); - else - return new C_MDC_OpenInoTraverseDir(this, ino); -} - void MDCache::_open_ino_traverse_dir(inodeno_t ino, open_ino_info_t& info, int ret) { dout(10) << __func__ << ": ino " << ino << " ret " << ret << dendl; @@ -8434,11 +8439,11 @@ void MDCache::_open_ino_traverse_dir(inodeno_t ino, open_ino_info_t& info, int r do_open_ino(ino, info, ret); } -void MDCache::_open_ino_fetch_dir(inodeno_t ino, MMDSOpenIno *m, CDir *dir) +void MDCache::_open_ino_fetch_dir(inodeno_t ino, MMDSOpenIno *m, CDir *dir, bool parent) { if (dir->state_test(CDir::STATE_REJOINUNDEF)) assert(dir->get_inode()->dirfragtree.is_leaf(dir->get_frag())); - dir->fetch(_open_ino_get_waiter(ino, m)); + dir->fetch(new C_MDC_OpenInoTraverseDir(this, ino, m, parent)); } int MDCache::open_ino_traverse_dir(inodeno_t ino, MMDSOpenIno *m, @@ -8452,7 +8457,7 @@ int MDCache::open_ino_traverse_dir(inodeno_t ino, MMDSOpenIno *m, if (!diri) { if (discover && MDS_INO_IS_MDSDIR(ancestors[i].dirino)) { - open_foreign_mdsdir(ancestors[i].dirino, _open_ino_get_waiter(ino, m)); + open_foreign_mdsdir(ancestors[i].dirino, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0)); return 1; } continue; @@ -8463,7 +8468,7 @@ int MDCache::open_ino_traverse_dir(inodeno_t ino, MMDSOpenIno *m, while (dir->state_test(CDir::STATE_REJOINUNDEF) && dir->get_inode()->state_test(CInode::STATE_REJOINUNDEF)) dir = dir->get_inode()->get_parent_dir(); - _open_ino_fetch_dir(ino, m, dir); + _open_ino_fetch_dir(ino, m, dir, i == 0); return 1; } @@ -8481,12 +8486,12 @@ int MDCache::open_ino_traverse_dir(inodeno_t ino, MMDSOpenIno *m, if (diri->is_auth()) { if (diri->is_frozen()) { dout(10) << " " << *diri << " is frozen, waiting " << dendl; - diri->add_waiter(CDir::WAIT_UNFREEZE, _open_ino_get_waiter(ino, m)); + diri->add_waiter(CDir::WAIT_UNFREEZE, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0)); return 1; } dir = diri->get_or_open_dirfrag(this, fg); } else if (discover) { - open_remote_dirfrag(diri, fg, _open_ino_get_waiter(ino, m)); + open_remote_dirfrag(diri, fg, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0)); return 1; } } @@ -8498,14 +8503,14 @@ int MDCache::open_ino_traverse_dir(inodeno_t ino, MMDSOpenIno *m, if (dnl && dnl->is_primary() && dnl->get_inode()->state_test(CInode::STATE_REJOINUNDEF)) { dout(10) << " fetching undef " << *dnl->get_inode() << dendl; - _open_ino_fetch_dir(ino, m, dir); + _open_ino_fetch_dir(ino, m, dir, i == 0); return 1; } if (!dnl && !dir->is_complete() && (!dir->has_bloom() || dir->is_in_bloom(name))) { dout(10) << " fetching incomplete " << *dir << dendl; - _open_ino_fetch_dir(ino, m, dir); + _open_ino_fetch_dir(ino, m, dir, i == 0); return 1; } @@ -8515,13 +8520,13 @@ int MDCache::open_ino_traverse_dir(inodeno_t ino, MMDSOpenIno *m, } else if (discover) { if (!dnl) { filepath path(name, 0); - discover_path(dir, CEPH_NOSNAP, path, _open_ino_get_waiter(ino, m), + discover_path(dir, CEPH_NOSNAP, path, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0), (i == 0 && want_xlocked)); return 1; } if (dnl->is_null() && !dn->lock.can_read(-1)) { dout(10) << " null " << *dn << " is not readable, waiting" << dendl; - dn->lock.add_waiter(SimpleLock::WAIT_RD, _open_ino_get_waiter(ino, m)); + dn->lock.add_waiter(SimpleLock::WAIT_RD, new C_MDC_OpenInoTraverseDir(this, ino, m, i == 0)); return 1; } dout(10) << " no ino " << next_ino << " in " << *dir << dendl; @@ -8548,7 +8553,7 @@ void MDCache::open_ino_finish(inodeno_t ino, open_ino_info_t& info, int ret) void MDCache::do_open_ino(inodeno_t ino, open_ino_info_t& info, int err) { - if (err < 0) { + if (err < 0 && err != -EAGAIN) { info.checked.clear(); info.checked.insert(mds->get_nodeid()); info.checking = MDS_RANK_NONE; @@ -8558,6 +8563,8 @@ void MDCache::do_open_ino(inodeno_t ino, open_ino_info_t& info, int err) info.discover = false; info.ancestors.clear(); } + if (err != -ENOENT && err != -ENOTDIR) + info.last_err = err; } if (info.check_peers) { @@ -8619,9 +8626,9 @@ void MDCache::do_open_ino_peer(inodeno_t ino, open_ino_info_t& info) } } -void MDCache::handle_open_ino(MMDSOpenIno *m) +void MDCache::handle_open_ino(MMDSOpenIno *m, int err) { - dout(10) << "handle_open_ino " << *m << dendl; + dout(10) << "handle_open_ino " << *m << " err " << err << dendl; inodeno_t ino = m->ino; MMDSOpenInoReply *reply; @@ -8643,6 +8650,8 @@ void MDCache::handle_open_ino(MMDSOpenIno *m) } else { reply->hint = in->authority().first; } + } else if (err < 0) { + reply = new MMDSOpenInoReply(m->get_tid(), ino, MDS_RANK_NONE, err); } else { mds_rank_t hint = MDS_RANK_NONE; int ret = open_ino_traverse_dir(ino, m, m->ancestors, false, false, &hint); diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index 9304f94df2a6d..a9c41193478a7 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -912,10 +912,12 @@ protected: bool want_xlocked; version_t tid; int64_t pool; + int last_err; list waiters; open_ino_info_t() : checking(MDS_RANK_NONE), auth_hint(MDS_RANK_NONE), check_peers(true), fetch_backtrace(true), discover(false), - want_replica(false), want_xlocked(false), tid(0), pool(-1) {} + want_replica(false), want_xlocked(false), tid(0), pool(-1), + last_err(0) {} }; ceph_tid_t open_ino_last_tid; map opening_inodes; @@ -923,15 +925,14 @@ protected: void _open_ino_backtrace_fetched(inodeno_t ino, bufferlist& bl, int err); void _open_ino_parent_opened(inodeno_t ino, int ret); void _open_ino_traverse_dir(inodeno_t ino, open_ino_info_t& info, int err); - void _open_ino_fetch_dir(inodeno_t ino, MMDSOpenIno *m, CDir *dir); - MDSInternalContextBase* _open_ino_get_waiter(inodeno_t ino, MMDSOpenIno *m); + void _open_ino_fetch_dir(inodeno_t ino, MMDSOpenIno *m, CDir *dir, bool parent); int open_ino_traverse_dir(inodeno_t ino, MMDSOpenIno *m, vector& ancestors, bool discover, bool want_xlocked, mds_rank_t *hint); void open_ino_finish(inodeno_t ino, open_ino_info_t& info, int err); void do_open_ino(inodeno_t ino, open_ino_info_t& info, int err); void do_open_ino_peer(inodeno_t ino, open_ino_info_t& info); - void handle_open_ino(MMDSOpenIno *m); + void handle_open_ino(MMDSOpenIno *m, int err=0); void handle_open_ino_reply(MMDSOpenInoReply *m); friend class C_IO_MDC_OpenInoBacktraceFetched; friend struct C_MDC_OpenInoTraverseDir; -- 2.39.5