Skip to content

Commit

Permalink
mds: wait for client to release shared cap when re-acquiring xlock
Browse files Browse the repository at this point in the history
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>
(cherry picked from commit 218e784)

Conflicts:
	src/mds/SimpleLock.h : Resolved in put_xlock
  • Loading branch information
ukernel authored and Prashant D committed Mar 18, 2019
1 parent 2b3c641 commit 38cee8b
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 13 deletions.
24 changes: 13 additions & 11 deletions src/mds/Locker.cc
Expand Up @@ -763,8 +763,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);
}
Expand Down Expand Up @@ -1650,11 +1649,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->xlocks.insert(lock);
Expand All @@ -1663,11 +1668,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 ||
Expand Down Expand Up @@ -1789,9 +1792,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);
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/mds/SimpleLock.h
Expand Up @@ -506,8 +506,9 @@ class SimpleLock {
}
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) {
Expand Down

0 comments on commit 38cee8b

Please sign in to comment.