]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: don't add not issued caps when confirming cap receipt
authorYan, Zheng <zheng.z.yan@intel.com>
Mon, 19 Nov 2012 02:43:35 +0000 (10:43 +0800)
committerSage Weil <sage@inktank.com>
Tue, 27 Nov 2012 05:14:45 +0000 (21:14 -0800)
There is message ordering race in cephfs kernel client. We compose
cap messages when i_ceph_lock is hold. But when adding messages
to the output queue, the kernel releases i_ceph_lock and acquires
a mutex. So it is possible that cap messages are send out of order.
If the kernel client send a cap update, then send a cap release,
but the two messages reach MDS out of order. The update message
will re-add the released caps. This patch adds code to check if
caps were actually issued when confirming cap receipt.

Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
src/mds/Locker.cc

index 9d917486eb1e0d1dc08bf7e682fbae12d9918f63..c29ac34ec850b8e71b0b5be8091beb82be599409 100644 (file)
@@ -2287,11 +2287,17 @@ void Locker::handle_client_caps(MClientCaps *m)
  
     // head inode, and cap
     MClientCaps *ack = 0;
+
+    int caps = m->get_caps();
+    if (caps & ~cap->issued()) {
+      dout(10) << " confirming not issued caps " << ccap_string(caps & ~cap->issued()) << dendl;
+      caps &= cap->issued();
+    }
     
-    cap->confirm_receipt(m->get_seq(), m->get_caps());
+    cap->confirm_receipt(m->get_seq(), caps);
     dout(10) << " follows " << follows
             << " retains " << ccap_string(m->get_caps())
-            << " dirty " << ccap_string(m->get_caps())
+            << " dirty " << ccap_string(m->get_dirty())
             << " on " << *in << dendl;
 
 
@@ -2424,6 +2430,10 @@ void Locker::process_request_cap_release(MDRequest *mdr, client_t client, const
     return;
   }
     
+  if (caps & ~cap->issued()) {
+    dout(10) << " confirming not issued caps " << ccap_string(caps & ~cap->issued()) << dendl;
+    caps &= cap->issued();
+  }
   cap->confirm_receipt(seq, caps);
   adjust_cap_wanted(cap, wanted, issue_seq);