]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: issue new caps to client even when session is stale
authorYan, Zheng <zyan@redhat.com>
Fri, 10 Feb 2017 09:31:37 +0000 (17:31 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 20 Feb 2017 08:12:36 +0000 (16:12 +0800)
If early reply is not allowed for open request, MDS does not send
reply to client immediately after adding adds new caps. Later when
MDS sends the reply, client session can be in stale stale. If MDS
does not issue the new caps to client along with the reply, the
new caps get lost. This issue can cause MDS to hang at revoking
caps.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/CInode.cc
src/mds/Capability.h
src/mds/Migrator.cc

index 51aefb0f02a9e4eb79bb97fdfc15d2036f781b8f..b04b4712bf34c28ab085c17ac6064440f3dd4341 100644 (file)
@@ -3240,12 +3240,26 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session,
       }
     }
 
+    int issue = 0;
     if (!no_caps && cap) {
       int likes = get_caps_liked();
       int allowed = get_caps_allowed_for_client(session, file_i);
-      int issue = (cap->wanted() | likes) & allowed;
+      issue = (cap->wanted() | likes) & allowed;
       cap->issue_norevoke(issue);
       issue = cap->pending();
+      dout(10) << "encode_inodestat issuing " << ccap_string(issue)
+              << " seq " << cap->get_last_seq() << dendl;
+    } else if (cap && cap->is_new() && !dir_realm) {
+      // alway issue new caps to client, otherwise the caps get lost
+      assert(cap->is_stale());
+      issue = cap->pending() | CEPH_CAP_PIN;
+      cap->issue_norevoke(issue);
+      dout(10) << "encode_inodestat issuing " << ccap_string(issue)
+              << " seq " << cap->get_last_seq()
+              << "(stale|new caps)" << dendl;
+    }
+
+    if (issue) {
       cap->set_last_issue();
       cap->set_last_issue_stamp(ceph_clock_now());
       cap->clear_new();
@@ -3253,13 +3267,9 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session,
       ecap.wanted = cap->wanted();
       ecap.cap_id = cap->get_cap_id();
       ecap.seq = cap->get_last_seq();
-      dout(10) << "encode_inodestat issuing " << ccap_string(issue)
-              << " seq " << cap->get_last_seq() << dendl;
       ecap.mseq = cap->get_mseq();
       ecap.realm = realm->inode->ino();
     } else {
-      if (cap)
-       cap->clear_new();
       ecap.cap_id = 0;
       ecap.caps = 0;
       ecap.seq = 0;
index b8ea0a1e732b6c6088eaae38d055a317a15e64d7..f2e5805075ae369520089a732b131922e2ff7adc 100644 (file)
@@ -107,6 +107,7 @@ public:
 
   const static unsigned STATE_STALE            = (1<<0);
   const static unsigned STATE_NEW              = (1<<1);
+  const static unsigned STATE_IMPORTING                = (1<<2);
 
 
   Capability(CInode *i = NULL, uint64_t id = 0, client_t c = 0) :
@@ -253,6 +254,9 @@ public:
   bool is_new() { return state & STATE_NEW; }
   void mark_new() { state |= STATE_NEW; }
   void clear_new() { state &= ~STATE_NEW; }
+  bool is_importing() { return state & STATE_IMPORTING; }
+  void mark_importing() { state |= STATE_IMPORTING; }
+  void clear_importing() { state &= ~STATE_IMPORTING; }
 
   CInode *get_inode() { return inode; }
   client_t get_client() const { return client; }
index 1fe1c862848217a2790164d9c12817bef7be2b5b..52df1588205402dc75a767423458f61af244d1ce 100644 (file)
@@ -2511,7 +2511,7 @@ void Migrator::import_reverse(CDir *dir)
          ++q) {
        Capability *cap = in->get_client_cap(q->first);
        assert(cap);
-       if (cap->is_new())
+       if (cap->is_importing())
          in->remove_client_cap(q->first);
       }
       in->put(CInode::PIN_IMPORTINGCAPS);
@@ -2705,6 +2705,7 @@ void Migrator::import_finish(CDir *dir, bool notify, bool last)
        Capability *cap = in->get_client_cap(q->first);
        assert(cap);
        cap->merge(q->second, true);
+       cap->clear_importing();
        mds->mdcache->do_cap_import(session, in, cap, q->second.cap_id, q->second.seq,
                                    q->second.mseq - 1, it->second.peer, CEPH_CAP_FLAG_AUTH);
       }
@@ -2879,7 +2880,7 @@ void Migrator::finish_import_inode_caps(CInode *in, mds_rank_t peer, bool auth_c
     if (!cap) {
       cap = in->add_client_cap(it->first, session);
       if (peer < 0)
-       cap->mark_new();
+       cap->mark_importing();
     }
 
     Capability::Import& im = import_map[it->first];