From: Yan, Zheng Date: Thu, 28 Feb 2019 13:36:28 +0000 (+0800) Subject: mds: wait for client to release shared cap when re-acquiring xlock X-Git-Tag: v12.2.12~22^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4ce6b7a7fa6788081cb93f1b71bd6b79a405c402;p=ceph.git mds: wait for client to release shared cap when re-acquiring xlock 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" (cherry picked from commit 218e784f2eb1eec6bbb7910b5432f7f36263dbe7) Conflicts: src/mds/SimpleLock.h : Resovled in put_xlock --- diff --git a/src/mds/Locker.cc b/src/mds/Locker.cc index ce50715973a..b2b4c21dc45 100644 --- a/src/mds/Locker.cc +++ b/src/mds/Locker.cc @@ -759,8 +759,7 @@ void Locker::cancel_locking(MutationImpl *mut, set *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); } @@ -1644,11 +1643,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(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->xlocks.insert(lock); @@ -1657,11 +1662,9 @@ bool Locker::xlock_start(SimpleLock *lock, MDRequestRef& mut) return true; } - if (lock->get_type() == CEPH_LOCK_IFILE) { - CInode *in = static_cast(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 || @@ -1782,9 +1785,8 @@ void Locker::xlock_finish(SimpleLock *lock, MutationImpl *mut, bool *pneed_issue 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); } } diff --git a/src/mds/SimpleLock.h b/src/mds/SimpleLock.h index 2c0ff9327c3..8e5c828fb20 100644 --- a/src/mds/SimpleLock.h +++ b/src/mds/SimpleLock.h @@ -506,8 +506,9 @@ public: } void put_xlock() { 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) {