]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: delay handling client caps until corresponding inode is created
authorYan, Zheng <zyan@redhat.com>
Tue, 12 Jan 2016 08:54:14 +0000 (16:54 +0800)
committerYan, Zheng <zyan@redhat.com>
Fri, 15 Jan 2016 05:19:05 +0000 (13:19 +0800)
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 <zyan@redhat.com>
src/mds/Locker.cc
src/mds/MDCache.cc
src/mds/MDCache.h

index 26a3f104d9e3e5da629d7cb7821c4e5a53270251..d956c03f3e37f797e924a121f1288ecd74192297 100644 (file)
@@ -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;
   }
index eddfcd441ff374eaf22c06fd44a90450010fd4cb..69d99b743776cfa7a3658e8b050c114b462fc563 100644 (file)
@@ -5524,8 +5524,14 @@ void MDCache::export_remaining_imported_caps()
     }
   }
 
+  for (map<inodeno_t, list<MDSInternalContextBase*> >::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<inodeno_t, list<MDSInternalContextBase*> >::iterator it =
+      cap_reconnect_waiters.find(in->ino());
+    if (it != cap_reconnect_waiters.end()) {
+      mds->queue_waiters(it->second);
+      cap_reconnect_waiters.erase(it);
+    }
   }
 }
 
index 921b03ad4ec3455251a6df91161e9b0dcb6105be..b7e9c057b7128586a999b9576ab1cde39eeda4dd 100644 (file)
@@ -493,6 +493,7 @@ protected:
   map<inodeno_t,map<client_t,map<mds_rank_t,ceph_mds_cap_reconnect> > > cap_imports;  // ino -> client -> frommds -> capex
   map<inodeno_t,int> cap_imports_dirty;
   set<inodeno_t> cap_imports_missing;
+  map<inodeno_t, list<MDSInternalContextBase*> > cap_reconnect_waiters;
   int cap_imports_num_opening;
   
   set<CInode*> 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<CInode*,map<client_t, inodeno_t> >  reconnected_caps;   // inode -> client -> realmino