Merge PR #18787 into master

* refs/pull/18787/head:
	mds: prevent filelock from being stuck at XSYN state
	mds: implement LOCK_XSYN_LOCK and LOCK_XSYN_MIX
	mds: cleanup set/drop loner code

Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
This commit is contained in:
Patrick Donnelly 2017-11-22 13:40:07 -08:00
commit de3662e460
No known key found for this signature in database
GPG Key ID: 3A2A7E25BEA8AADB
6 changed files with 47 additions and 45 deletions

View File

@ -2751,10 +2751,24 @@ client_t CInode::calc_ideal_loner()
return loner;
}
client_t CInode::choose_ideal_loner()
bool CInode::choose_ideal_loner()
{
want_loner_cap = calc_ideal_loner();
return want_loner_cap;
int changed = false;
if (loner_cap >= 0 && loner_cap != want_loner_cap) {
if (!try_drop_loner())
return false;
changed = true;
}
if (want_loner_cap >= 0) {
if (loner_cap < 0) {
set_loner_cap(want_loner_cap);
changed = true;
} else
assert(loner_cap == want_loner_cap);
}
return changed;
}
bool CInode::try_set_loner()
@ -2822,9 +2836,8 @@ void CInode::choose_lock_state(SimpleLock *lock, int allissued)
void CInode::choose_lock_states(int dirty_caps)
{
int issued = get_caps_issued() | dirty_caps;
if (is_auth() && (issued & (CEPH_CAP_ANY_EXCL|CEPH_CAP_ANY_WR)) &&
choose_ideal_loner() >= 0)
try_set_loner();
if (is_auth() && (issued & (CEPH_CAP_ANY_EXCL|CEPH_CAP_ANY_WR)))
choose_ideal_loner();
choose_lock_state(&filelock, issued);
choose_lock_state(&nestlock, issued);
choose_lock_state(&dirfragtreelock, issued);
@ -3314,12 +3327,8 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session,
if (!no_caps && !cap) {
// add a new cap
cap = add_client_cap(client, session, realm);
if (is_auth()) {
if (choose_ideal_loner() >= 0)
try_set_loner();
else if (get_wanted_loner() < 0)
try_drop_loner();
}
if (is_auth())
choose_ideal_loner();
}
int issue = 0;

View File

@ -936,9 +936,9 @@ public:
}
client_t calc_ideal_loner();
client_t choose_ideal_loner();
bool try_set_loner();
void set_loner_cap(client_t l);
bool choose_ideal_loner();
bool try_set_loner();
bool try_drop_loner();
// choose new lock state during recovery, based on issued caps

View File

@ -958,6 +958,7 @@ void Locker::eval_gather(SimpleLock *lock, bool first, bool *pneed_issue, list<M
case LOCK_TSYN_MIX:
case LOCK_SYNC_MIX:
case LOCK_EXCL_MIX:
case LOCK_XSYN_MIX:
in->start_scatter(static_cast<ScatterLock *>(lock));
if (lock->get_parent()->is_replicated()) {
bufferlist softdata;
@ -1038,15 +1039,15 @@ bool Locker::eval(CInode *in, int mask, bool caps_imported)
// choose loner?
if (in->is_auth() && in->is_head()) {
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;
client_t orig_loner = in->get_loner();
if (in->choose_ideal_loner()) {
dout(10) << "eval set loner: client." << orig_loner << " -> client." << in->get_loner() << dendl;
need_issue = true;
mask = -1;
} else if (in->get_wanted_loner() != in->get_loner()) {
dout(10) << "eval want loner: client." << in->get_wanted_loner() << " but failed to set it" << dendl;
mask = -1;
}
}
retry:
@ -1067,19 +1068,14 @@ bool Locker::eval(CInode *in, int mask, bool caps_imported)
// drop loner?
if (in->is_auth() && in->is_head() && in->get_wanted_loner() != in->get_loner()) {
dout(10) << " trying to drop loner" << dendl;
if (in->try_drop_loner()) {
dout(10) << " dropped loner" << dendl;
need_issue = true;
if (in->get_wanted_loner() >= 0) {
if (in->try_set_loner()) {
dout(10) << "eval end set loner to client." << in->get_loner() << dendl;
mask = -1;
goto retry;
} else {
dout(10) << "eval want loner client." << in->get_wanted_loner() << " but failed to set it" << dendl;
}
dout(10) << "eval end set loner to client." << in->get_loner() << dendl;
bool ok = in->try_set_loner();
assert(ok);
mask = -1;
goto retry;
}
}
}
@ -4187,11 +4183,7 @@ void Locker::simple_lock(SimpleLock *lock, bool *need_issue)
switch (lock->get_state()) {
case LOCK_SYNC: lock->set_state(LOCK_SYNC_LOCK); break;
case LOCK_XSYN:
file_excl(static_cast<ScatterLock*>(lock), need_issue);
if (lock->get_state() != LOCK_EXCL)
return;
// fall-thru
case LOCK_XSYN: lock->set_state(LOCK_XSYN_LOCK); break;
case LOCK_EXCL: lock->set_state(LOCK_EXCL_LOCK); break;
case LOCK_MIX: lock->set_state(LOCK_MIX_LOCK);
(static_cast<ScatterLock *>(lock))->clear_unscatter_wanted();
@ -4858,7 +4850,7 @@ void Locker::file_eval(ScatterLock *lock, bool *need_issue)
!lock->is_rdlocked() &&
//!lock->is_waiter_for(SimpleLock::WAIT_WR) &&
(lock->get_scatter_wanted() ||
(in->get_wanted_loner() < 0 && (wanted & CEPH_CAP_GWR)))) {
(in->get_target_loner() < 0 && (wanted & CEPH_CAP_GWR)))) {
dout(7) << "file_eval stable, bump to mixed " << *lock
<< " on " << *lock->get_parent() << dendl;
scatter_mix(lock, need_issue);
@ -4916,12 +4908,8 @@ void Locker::scatter_mix(ScatterLock *lock, bool *need_issue)
// gather?
switch (lock->get_state()) {
case LOCK_SYNC: lock->set_state(LOCK_SYNC_MIX); break;
case LOCK_XSYN:
file_excl(lock, need_issue);
if (lock->get_state() != LOCK_EXCL)
return;
// fall-thru
case LOCK_EXCL: lock->set_state(LOCK_EXCL_MIX); break;
case LOCK_XSYN: lock->set_state(LOCK_XSYN_MIX); break;
case LOCK_TSYN: lock->set_state(LOCK_TSYN_MIX); break;
default: ceph_abort();
}
@ -4930,8 +4918,7 @@ void Locker::scatter_mix(ScatterLock *lock, bool *need_issue)
if (lock->is_rdlocked())
gather++;
if (in->is_replicated()) {
if (lock->get_state() != LOCK_EXCL_MIX && // EXCL replica is already LOCK
lock->get_state() != LOCK_XSYN_EXCL) { // XSYN replica is already LOCK; ** FIXME here too!
if (lock->get_state() == LOCK_SYNC_MIX) { // for the rest states, replicas are already LOCK
send_lock_message(lock, LOCK_AC_MIX);
lock->init_gather();
gather++;

View File

@ -120,6 +120,8 @@ public:
case LOCK_XSYN_EXCL: return "xsyn->excl";
case LOCK_EXCL_XSYN: return "excl->xsyn";
case LOCK_XSYN_SYNC: return "xsyn->sync";
case LOCK_XSYN_LOCK: return "xsyn->lock";
case LOCK_XSYN_MIX: return "xsyn->mix";
case LOCK_SYNC_MIX: return "sync->mix";
case LOCK_SYNC_MIX2: return "sync->mix(2)";

View File

@ -95,6 +95,7 @@ const struct sm_state_t filelock[LOCK_MAX] = {
[LOCK_EXCL_LOCK] = { LOCK_LOCK, false, LOCK_LOCK, 0, 0, 0, 0, XCL, 0, 0, CEPH_CAP_GCACHE|CEPH_CAP_GBUFFER,0,0,0 },
[LOCK_MIX_LOCK] = { LOCK_LOCK, false, LOCK_MIX, AUTH, 0, REQ, 0, 0, 0, 0, 0,0,0,0 },
[LOCK_MIX_LOCK2] = { LOCK_LOCK, false, LOCK_LOCK, AUTH, 0, REQ, 0, 0, 0, 0, 0,0,0,0 },
[LOCK_XSYN_LOCK] = { LOCK_LOCK, true, LOCK_LOCK, AUTH, 0, 0, XCL, 0, 0, 0, 0,CEPH_CAP_GCACHE|CEPH_CAP_GBUFFER,0,0 },
[LOCK_PREXLOCK] = { LOCK_LOCK, false, LOCK_LOCK, 0, XCL, 0, 0, 0, 0, ANY, CEPH_CAP_GCACHE|CEPH_CAP_GBUFFER,0,0,0 },
[LOCK_XLOCK] = { LOCK_LOCK, false, LOCK_LOCK, 0, XCL, 0, 0, 0, 0, 0, CEPH_CAP_GCACHE|CEPH_CAP_GBUFFER,0,0,0 },
@ -106,6 +107,7 @@ const struct sm_state_t filelock[LOCK_MAX] = {
[LOCK_SYNC_MIX] = { LOCK_MIX, false, LOCK_SYNC_MIX2,ANY,0, 0, 0, 0, 0, 0, CEPH_CAP_GRD|CEPH_CAP_GLAZYIO,0,0,CEPH_CAP_GRD },
[LOCK_SYNC_MIX2] = { LOCK_MIX, false, 0, 0, 0, 0, 0, 0, 0, 0, CEPH_CAP_GRD|CEPH_CAP_GLAZYIO,0,0,CEPH_CAP_GRD },
[LOCK_EXCL_MIX] = { LOCK_MIX, true, LOCK_LOCK, 0, 0, 0, XCL, 0, 0, 0, 0,CEPH_CAP_GRD|CEPH_CAP_GWR|CEPH_CAP_GLAZYIO,0,0 },
[LOCK_XSYN_MIX] = { LOCK_MIX, true, LOCK_LOCK, 0, 0, 0, XCL, 0, 0, 0, 0,0,0,0 },
[LOCK_EXCL] = { 0, true, LOCK_LOCK, 0, 0, XCL, XCL, 0, 0, 0, 0,CEPH_CAP_GSHARED|CEPH_CAP_GEXCL|CEPH_CAP_GCACHE|CEPH_CAP_GRD|CEPH_CAP_GWR|CEPH_CAP_GBUFFER|CEPH_CAP_GLAZYIO,0,0 },
[LOCK_SYNC_EXCL] = { LOCK_EXCL, true, LOCK_LOCK, AUTH, 0, 0, 0, 0, 0, 0, 0,CEPH_CAP_GSHARED|CEPH_CAP_GCACHE|CEPH_CAP_GRD,0,0 },

View File

@ -94,6 +94,8 @@ enum {
LOCK_XSYN_EXCL,
LOCK_EXCL_XSYN,
LOCK_XSYN_SYNC,
LOCK_XSYN_LOCK,
LOCK_XSYN_MIX,
LOCK_MAX,
};