]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: wait for client to release shared cap when re-acquiring xlock 26713/head
authorYan, Zheng <zyan@redhat.com>
Thu, 28 Feb 2019 13:36:28 +0000 (21:36 +0800)
committerYan, Zheng <zyan@redhat.com>
Fri, 1 Mar 2019 07:37:06 +0000 (15:37 +0800)
MDS may revoke shared cap from xlocker client during 'LOCK_XLOCKDONE ->
LOCK_LOCK_XLOCK' state transition.

Fixes: http://tracker.ceph.com/issues/38491
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/Locker.cc
src/mds/SimpleLock.h

index 5239dd270f0c7b577e8920cb58a0b1f21e230b45..584cf3b59fb030b02b002aad3ea70ed3ab16033b 100644 (file)
@@ -721,8 +721,7 @@ void Locker::cancel_locking(MutationImpl *mut, set<CInode*> *pneed_issue)
     bool need_issue = false;
     if (lock->get_state() == LOCK_PREXLOCK) {
       _finish_xlock(lock, -1, &need_issue);
-    } else if (lock->get_state() == LOCK_LOCK_XLOCK &&
-              lock->get_num_xlocks() == 0) {
+    } else if (lock->get_state() == LOCK_LOCK_XLOCK) {
       lock->set_state(LOCK_XLOCKDONE);
       eval_gather(lock, true, &need_issue);
     }
@@ -1605,11 +1604,17 @@ bool Locker::xlock_start(SimpleLock *lock, MDRequestRef& mut)
   dout(7) << "xlock_start on " << *lock << " on " << *lock->get_parent() << dendl;
   client_t client = mut->get_client();
 
+  CInode *in = nullptr;
+  if (lock->get_cap_shift())
+    in = static_cast<CInode *>(lock->get_parent());
+
   // auth?
   if (lock->get_parent()->is_auth()) {
     // auth
     while (1) {
-      if (lock->can_xlock(client)) {
+      if (lock->can_xlock(client) &&
+         !(lock->get_state() == LOCK_LOCK_XLOCK &&     // client is not xlocker or
+           in && in->issued_caps_need_gather(lock))) { // xlocker does not hold shared cap
        lock->set_state(LOCK_XLOCK);
        lock->get_xlock(mut, client);
        mut->locks.emplace_hint(mut->locks.end(), lock, MutationImpl::LockOp::XLOCK);
@@ -1617,11 +1622,9 @@ bool Locker::xlock_start(SimpleLock *lock, MDRequestRef& mut)
        return true;
       }
       
-      if (lock->get_type() == CEPH_LOCK_IFILE) {
-       CInode *in = static_cast<CInode*>(lock->get_parent());
-       if (in->state_test(CInode::STATE_RECOVERING)) {
-         mds->mdcache->recovery_queue.prioritize(in);
-       }
+      if (lock->get_type() == CEPH_LOCK_IFILE &&
+         in->state_test(CInode::STATE_RECOVERING)) {
+       mds->mdcache->recovery_queue.prioritize(in);
       }
 
       if (!lock->is_stable() && (lock->get_state() != LOCK_XLOCKDONE ||
@@ -1743,9 +1746,8 @@ void Locker::xlock_finish(const MutationImpl::lock_iterator& it, MutationImpl *m
                         SimpleLock::WAIT_WR | 
                         SimpleLock::WAIT_RD, 0); 
   } else {
-    if (lock->get_num_xlocks() == 0) {
-      if (lock->get_state() == LOCK_LOCK_XLOCK)
-       lock->set_state(LOCK_XLOCKDONE);
+    if (lock->get_num_xlocks() == 0 &&
+        lock->get_state() != LOCK_LOCK_XLOCK) { // no one is taking xlock
       _finish_xlock(lock, xlocker, &do_issue);
     }
   }
index a14f37c859fe58ff61be30d33d11f840466549dc..c5ef94e6e6dec4d3bae6a6cd6ee8d592d34a41fb 100644 (file)
@@ -523,8 +523,9 @@ public:
   }
   void put_xlock() {
     ceph_assert(state == LOCK_XLOCK || state == LOCK_XLOCKDONE ||
-          state == LOCK_XLOCKSNAP || is_locallock() ||
-          state == LOCK_LOCK /* if we are a master of a slave */);
+          state == LOCK_XLOCKSNAP || state == LOCK_LOCK_XLOCK ||
+          state == LOCK_LOCK  || /* if we are a master of a slave */
+          is_locallock());
     --more()->num_xlock;
     parent->put(MDSCacheObject::PIN_LOCK);
     if (more()->num_xlock == 0) {