From: Yan, Zheng Date: Tue, 12 Jan 2016 08:54:14 +0000 (+0800) Subject: mds: delay handling client caps until corresponding inode is created X-Git-Tag: v10.0.3~12^2~2^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=dafb46ba7b49cddf4d1c0c842c67851744ec82f9;p=ceph.git mds: delay handling client caps until corresponding inode is created When handling client caps in clientreplay stage, it's possible that corresponding inode does not exist because the client request which creates inode hasn't been replayed. To handle this corner case, we delay handling caps message until corresponding inode is created. Fixes: #14254 Signed-off-by: Yan, Zheng --- diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index 26a3f104d9e3..d956c03f3e37 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -2517,7 +2517,13 @@ void Locker::handle_client_caps(MClientCaps *m) CInode *head_in = mdcache->get_inode(m->get_ino()); if (!head_in) { - dout(7) << "handle_client_caps on unknown ino " << m->get_ino() << ", dropping" << dendl; + if (mds->is_clientreplay()) { + dout(7) << "handle_client_caps on unknown ino " << m->get_ino() + << ", will try again after replayed client requests" << dendl; + mdcache->wait_replay_cap_reconnect(m->get_ino(), new C_MDS_RetryMessage(mds, m)); + return; + } + dout(1) << "handle_client_caps on unknown ino " << m->get_ino() << ", dropping" << dendl; m->put(); return; } diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index eddfcd441ff3..69d99b743776 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -5524,8 +5524,14 @@ void MDCache::export_remaining_imported_caps() } } + for (map >::iterator p = cap_reconnect_waiters.begin(); + p != cap_reconnect_waiters.end(); + ++p) + mds->queue_waiters(p->second); + cap_imports.clear(); cap_imports_dirty.clear(); + cap_reconnect_waiters.clear(); if (warn_str.peek() != EOF) { mds->clog->warn() << "failed to reconnect caps for missing inodes:" << "\n"; @@ -5555,6 +5561,13 @@ void MDCache::try_reconnect_cap(CInode *in, Session *session) in->choose_lock_states(dirty_caps); dout(15) << " chose lock states on " << *in << dendl; } + + map >::iterator it = + cap_reconnect_waiters.find(in->ino()); + if (it != cap_reconnect_waiters.end()) { + mds->queue_waiters(it->second); + cap_reconnect_waiters.erase(it); + } } } diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index 921b03ad4ec3..b7e9c057b712 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -493,6 +493,7 @@ protected: map > > cap_imports; // ino -> client -> frommds -> capex map cap_imports_dirty; set cap_imports_missing; + map > cap_reconnect_waiters; int cap_imports_num_opening; set rejoin_undef_inodes; @@ -551,6 +552,9 @@ public: void set_reconnect_dirty_caps(inodeno_t ino, int dirty) { cap_imports_dirty[ino] |= dirty; } + void wait_replay_cap_reconnect(inodeno_t ino, MDSInternalContextBase *c) { + cap_reconnect_waiters[ino].push_back(c); + } // [reconnect/rejoin caps] map > reconnected_caps; // inode -> client -> realmino