mirror of
https://github.com/ceph/ceph
synced 2025-03-11 02:39:05 +00:00
mds: clean up loner set/drop logic
Track what loner we _want_ separately from what loner we have, so that locks can move toward the right state. Centralize loner set/drop call points. Move out of EXCL in simple_eval if our target loner is -1(none).
This commit is contained in:
parent
0266f877ad
commit
c55f2e9812
1
src/TODO
1
src/TODO
@ -117,6 +117,7 @@ uclient
|
||||
- hadoop: clean up assert usage
|
||||
|
||||
mds
|
||||
- pass issued, wanted into eval(lock) when eval() already has it? (and otherwise optimize eval paths..)
|
||||
- add an up:shadow mode?
|
||||
- tail the mds log as it is written
|
||||
- periodically check head so that we trim, too
|
||||
|
@ -151,8 +151,12 @@ ostream& operator<<(ostream& out, CInode& in)
|
||||
<< "@" << it->second->get_last_sent();
|
||||
}
|
||||
out << "}";
|
||||
if (in.get_loner() >= 0)
|
||||
if (in.get_loner() >= 0 || in.get_wanted_loner() >= 0) {
|
||||
out << ",l=" << in.get_loner();
|
||||
if (in.get_loner() != in.get_wanted_loner())
|
||||
out << "(" << in.get_wanted_loner() << ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (in.get_num_ref()) {
|
||||
@ -1593,8 +1597,12 @@ bool CInode::encode_inodestat(bufferlist& bl, Session *session,
|
||||
if (!no_caps && valid && !cap) {
|
||||
// add a new cap
|
||||
cap = add_client_cap(client, session, find_snaprealm());
|
||||
if (is_auth())
|
||||
try_choose_loner();
|
||||
if (is_auth()) {
|
||||
if (choose_ideal_loner() >= 0)
|
||||
try_set_loner();
|
||||
else if (get_wanted_loner() < 0)
|
||||
try_drop_loner();
|
||||
}
|
||||
}
|
||||
|
||||
if (cap && valid) {
|
||||
|
@ -334,7 +334,7 @@ private:
|
||||
xattrlock(this, CEPH_LOCK_IXATTR, WAIT_XATTRLOCK_OFFSET),
|
||||
snaplock(this, CEPH_LOCK_ISNAP, WAIT_SNAPLOCK_OFFSET),
|
||||
nestlock(this, CEPH_LOCK_INEST, WAIT_NESTLOCK_OFFSET),
|
||||
loner_cap(-1)
|
||||
loner_cap(-1), want_loner_cap(-1)
|
||||
{
|
||||
g_num_ino++;
|
||||
g_num_inoa++;
|
||||
@ -534,14 +534,22 @@ public:
|
||||
|
||||
// -- caps -- (new)
|
||||
// client caps
|
||||
int loner_cap;
|
||||
int loner_cap, want_loner_cap;
|
||||
|
||||
bool try_choose_loner() {
|
||||
if (loner_cap >= 0)
|
||||
return true;
|
||||
int get_loner() { return loner_cap; }
|
||||
int get_wanted_loner() { return want_loner_cap; }
|
||||
|
||||
// this is the loner state our locks should aim for
|
||||
int get_target_loner() {
|
||||
if (loner_cap == want_loner_cap)
|
||||
return loner_cap;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int calc_ideal_loner() {
|
||||
if (!mds_caps_wanted.empty())
|
||||
return false;
|
||||
return -1;
|
||||
|
||||
int n = 0;
|
||||
int loner = -1;
|
||||
@ -549,24 +557,30 @@ public:
|
||||
it != client_caps.end();
|
||||
it++)
|
||||
if (!it->second->is_stale() &&
|
||||
((it->second->wanted() & (CEPH_CAP_ANY_WR|CEPH_CAP_FILE_WR|CEPH_CAP_FILE_RD))
|
||||
|| inode.is_dir())) {
|
||||
((it->second->wanted() & (CEPH_CAP_ANY_WR|CEPH_CAP_FILE_WR|CEPH_CAP_FILE_RD)) ||
|
||||
(inode.is_dir() && !has_subtree_root_dirfrag()))) {
|
||||
if (n)
|
||||
return false;
|
||||
return -1;
|
||||
n++;
|
||||
loner = it->first;
|
||||
}
|
||||
if (n == 1) {
|
||||
loner_cap = loner;
|
||||
authlock.excl_client = loner;
|
||||
filelock.excl_client = loner;
|
||||
linklock.excl_client = loner;
|
||||
xattrlock.excl_client = loner;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return loner;
|
||||
}
|
||||
int choose_ideal_loner() {
|
||||
want_loner_cap = calc_ideal_loner();
|
||||
return want_loner_cap;
|
||||
}
|
||||
bool try_set_loner() {
|
||||
assert(want_loner_cap >= 0);
|
||||
if (loner_cap >= 0 && loner_cap != want_loner_cap)
|
||||
return false;
|
||||
loner_cap = want_loner_cap;
|
||||
authlock.excl_client = loner_cap;
|
||||
filelock.excl_client = loner_cap;
|
||||
linklock.excl_client = loner_cap;
|
||||
xattrlock.excl_client = loner_cap;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_drop_loner() {
|
||||
if (loner_cap < 0)
|
||||
return true;
|
||||
@ -605,8 +619,9 @@ public:
|
||||
}
|
||||
void choose_lock_states() {
|
||||
int issued = get_caps_issued();
|
||||
if (is_auth() && (issued & CEPH_CAP_ANY_EXCL))
|
||||
try_choose_loner();
|
||||
if (is_auth() && (issued & (CEPH_CAP_ANY_EXCL|CEPH_CAP_ANY_WR)) &&
|
||||
choose_ideal_loner() >= 0)
|
||||
try_set_loner();
|
||||
choose_lock_state(&filelock, issued);
|
||||
choose_lock_state(&authlock, issued);
|
||||
choose_lock_state(&xattrlock, issued);
|
||||
@ -634,9 +649,6 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int get_loner() {
|
||||
return loner_cap;
|
||||
}
|
||||
|
||||
bool is_any_caps() { return !client_caps.empty(); }
|
||||
bool is_any_nonstale_caps() { return count_nonstale_caps(); }
|
||||
|
@ -525,8 +525,7 @@ void Locker::eval_gather(SimpleLock *lock, bool first, bool *need_issue)
|
||||
|
||||
// drop loner before doing waiters
|
||||
if (caps &&
|
||||
in->is_auth() && in->get_loner() >= 0 &&
|
||||
in->multiple_nonstale_caps()) {
|
||||
in->is_auth() && in->get_loner() >= 0 && in->get_wanted_loner() < 0) {
|
||||
dout(10) << " trying to drop loner" << dendl;
|
||||
if (in->try_drop_loner()) {
|
||||
dout(10) << " dropped loner" << dendl;
|
||||
@ -557,18 +556,18 @@ bool Locker::eval(CInode *in, int mask)
|
||||
dout(10) << "eval " << mask << " " << *in << dendl;
|
||||
|
||||
// choose loner?
|
||||
if (in->is_auth() && in->get_loner() < 0) {
|
||||
int wanted = in->get_caps_wanted();
|
||||
if (((wanted & (CEPH_CAP_GWR|CEPH_CAP_GBUFFER|CEPH_CAP_GEXCL)) ||
|
||||
(in->inode.is_dir() && !in->has_subtree_root_dirfrag() &&
|
||||
!in->multiple_nonstale_caps())) &&
|
||||
in->try_choose_loner()) {
|
||||
dout(10) << " chose loner client" << in->get_loner() << dendl;
|
||||
need_issue = true;
|
||||
mask = -1;
|
||||
}
|
||||
if (in->is_auth()) {
|
||||
if (in->choose_ideal_loner() >= 0) {
|
||||
if (in->try_set_loner()) {
|
||||
dout(10) << "eval set loner to client" << in->get_loner() << dendl;
|
||||
need_issue = true;
|
||||
mask = -1;
|
||||
} else
|
||||
dout(10) << "eval want loner client" << in->get_wanted_loner() << " but failed to set it" << dendl;
|
||||
} else
|
||||
dout(10) << "eval doesn't want loner" << dendl;
|
||||
}
|
||||
|
||||
|
||||
if (mask & CEPH_LOCK_IFILE)
|
||||
eval_any(&in->filelock, &need_issue);
|
||||
if (mask & CEPH_LOCK_IAUTH)
|
||||
@ -581,8 +580,7 @@ bool Locker::eval(CInode *in, int mask)
|
||||
eval_any(&in->nestlock, &need_issue);
|
||||
|
||||
// drop loner?
|
||||
if (in->is_auth() && in->get_loner() >= 0 &&
|
||||
in->multiple_nonstale_caps()) {
|
||||
if (in->is_auth() && in->get_loner() >= 0 && in->get_wanted_loner() < 0) {
|
||||
dout(10) << " trying to drop loner" << dendl;
|
||||
if (in->try_drop_loner()) {
|
||||
dout(10) << " dropped loner" << dendl;
|
||||
@ -1463,7 +1461,7 @@ bool Locker::check_inode_max_size(CInode *in, bool force_wrlock,
|
||||
if (!force_wrlock && !in->filelock.can_wrlock(in->get_loner())) {
|
||||
// lock?
|
||||
if (in->filelock.is_stable()) {
|
||||
if (in->get_loner() >= 0)
|
||||
if (in->get_target_loner() >= 0)
|
||||
file_excl(&in->filelock);
|
||||
else
|
||||
simple_lock(&in->filelock);
|
||||
@ -1880,7 +1878,7 @@ bool Locker::_do_cap_update(CInode *in, Capability *cap,
|
||||
if (in->filelock.is_stable()) {
|
||||
bool need_issue = false;
|
||||
cap->inc_suppress();
|
||||
if (in->get_loner() >= 0 || in->try_choose_loner()) {
|
||||
if (in->get_loner() >= 0 || (in->get_wanted_loner() >= 0 && in->try_set_loner())) {
|
||||
if (in->filelock.get_state() != LOCK_EXCL)
|
||||
file_excl(&in->filelock, &need_issue);
|
||||
need_issue = false; // loner!
|
||||
@ -2469,7 +2467,7 @@ void Locker::simple_eval(SimpleLock *lock, bool *need_issue)
|
||||
|
||||
// -> excl?
|
||||
if (lock->get_state() != LOCK_EXCL &&
|
||||
in && in->get_loner() >= 0 &&
|
||||
in && in->get_target_loner() >= 0 &&
|
||||
(wanted & CEPH_CAP_GEXCL)) {
|
||||
dout(7) << "simple_eval stable, going to excl " << *lock
|
||||
<< " on " << *lock->get_parent() << dendl;
|
||||
@ -2480,8 +2478,9 @@ void Locker::simple_eval(SimpleLock *lock, bool *need_issue)
|
||||
else if (lock->get_state() != LOCK_SYNC &&
|
||||
!lock->is_xlocked() &&
|
||||
!lock->is_wrlocked() &&
|
||||
!(issued & CEPH_CAP_GEXCL) &&
|
||||
!lock->is_waiter_for(SimpleLock::WAIT_WR)) {
|
||||
((!(issued & CEPH_CAP_GEXCL) &&
|
||||
!lock->is_waiter_for(SimpleLock::WAIT_WR)) ||
|
||||
(lock->get_state() == LOCK_EXCL && in && in->get_target_loner() < 0))) {
|
||||
dout(7) << "simple_eval stable, syncing " << *lock
|
||||
<< " on " << *lock->get_parent() << dendl;
|
||||
simple_sync(lock, need_issue);
|
||||
@ -3138,7 +3137,7 @@ void Locker::file_eval(ScatterLock *lock, bool *need_issue)
|
||||
//!lock->is_waiter_for(SimpleLock::WAIT_WR) &&
|
||||
((wanted & (CEPH_CAP_GWR|CEPH_CAP_GBUFFER)) ||
|
||||
(in->inode.is_dir() && !in->has_subtree_root_dirfrag())) &&
|
||||
in->try_choose_loner()) {
|
||||
in->get_target_loner() >= 0) {
|
||||
dout(7) << "file_eval stable, bump to loner " << *lock
|
||||
<< " on " << *lock->get_parent() << dendl;
|
||||
file_excl(lock, need_issue);
|
||||
|
Loading…
Reference in New Issue
Block a user