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 26a3f104d9e..d956c03f3e3 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 eddfcd441ff..69d99b74377 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 921b03ad4ec..b7e9c057b71 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