@@ -546,9 +546,7 @@ void Locker::cancel_locking(Mutation *mut, set<CInode*> *pneed_issue)
if (lock->get_type() != CEPH_LOCK_DN) {
bool need_issue = false;
if (lock->get_state() == LOCK_PREXLOCK)
- _finish_xlock(lock, &need_issue);
- if (lock->is_stable())
- eval(lock, &need_issue);
+ _finish_xlock(lock, -1, &need_issue);
if (need_issue)
pneed_issue->insert(static_cast<CInode *>(lock->get_parent()));
}
@@ -1458,19 +1456,29 @@ bool Locker::xlock_start(SimpleLock *lock, MDRequest *mut)
}
}
-void Locker::_finish_xlock(SimpleLock *lock, bool *pneed_issue)
+void Locker::_finish_xlock(SimpleLock *lock, client_t xlocker, bool *pneed_issue)
{
assert(!lock->is_stable());
- if (lock->get_type() != CEPH_LOCK_DN && (static_cast<CInode*>(lock->get_parent())->get_loner()) >= 0)
- lock->set_state(LOCK_EXCL);
- else
- lock->set_state(LOCK_LOCK);
- if (lock->get_type() == CEPH_LOCK_DN && lock->get_parent()->is_replicated() &&
- !lock->is_waiter_for(SimpleLock::WAIT_WR))
- simple_sync(lock, pneed_issue);
- if (lock->get_cap_shift())
- *pneed_issue = true;
- lock->get_parent()->auth_unpin(lock);
+ if (lock->get_num_rdlocks() == 0 &&
+ lock->get_num_wrlocks() == 0 &&
+ lock->get_num_client_lease() == 0 &&
+ lock->get_type() != CEPH_LOCK_DN) {
+ CInode *in = static_cast<CInode*>(lock->get_parent());
+ client_t loner = in->get_target_loner();
+ if (loner >= 0 && (xlocker < 0 || xlocker == loner)) {
+ lock->set_state(LOCK_EXCL);
+ lock->get_parent()->auth_unpin(lock);
+ lock->finish_waiters(SimpleLock::WAIT_STABLE|SimpleLock::WAIT_WR|SimpleLock::WAIT_RD);
+ if (lock->get_cap_shift())
+ *pneed_issue = true;
+ if (lock->get_parent()->is_auth() &&
+ lock->is_stable())
+ try_eval(lock, pneed_issue);
+ return;
+ }
+ }
+ // the xlocker may have CEPH_CAP_GSHARED, need to revoke it if next state is LOCK_LOCK
+ eval_gather(lock, true, pneed_issue);
}
void Locker::xlock_finish(SimpleLock *lock, Mutation *mut, bool *pneed_issue)
@@ -1481,6 +1489,8 @@ void Locker::xlock_finish(SimpleLock *lock, Mutation *mut, bool *pneed_issue)
dout(10) << "xlock_finish on " << *lock << " " << *lock->get_parent() << dendl;
+ client_t xlocker = lock->get_xlock_by_client();
+
// drop ref
lock->put_xlock();
assert(mut);
@@ -1508,24 +1518,9 @@ void Locker::xlock_finish(SimpleLock *lock, Mutation *mut, bool *pneed_issue)
SimpleLock::WAIT_WR |
SimpleLock::WAIT_RD, 0);
} else {
- if (lock->get_num_xlocks() == 0 &&
- lock->get_num_rdlocks() == 0 &&
- lock->get_num_wrlocks() == 0 &&
- lock->get_num_client_lease() == 0) {
- _finish_xlock(lock, &do_issue);
- }
-
- // others waiting?
- lock->finish_waiters(SimpleLock::WAIT_STABLE |
- SimpleLock::WAIT_WR |
- SimpleLock::WAIT_RD, 0);
+ if (lock->get_num_xlocks() == 0)
+ _finish_xlock(lock, xlocker, &do_issue);
}
-
- // eval?
- if (!lock->is_stable())
- eval_gather(lock, false, &do_issue);
- else if (lock->get_parent()->is_auth())
- try_eval(lock, &do_issue);
if (do_issue) {
CInode *in = static_cast<CInode*>(lock->get_parent());
@@ -143,7 +143,7 @@ public:
void remote_wrlock_finish(SimpleLock *lock, int target, Mutation *mut);
bool xlock_start(SimpleLock *lock, MDRequest *mut);
- void _finish_xlock(SimpleLock *lock, bool *pneed_issue);
+ void _finish_xlock(SimpleLock *lock, client_t xlocker, bool *pneed_issue);
void xlock_finish(SimpleLock *lock, Mutation *mut, bool *pneed_issue);
void xlock_export(SimpleLock *lock, Mutation *mut);