mirror of
https://github.com/ceph/ceph
synced 2025-02-23 11:07:35 +00:00
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:
commit
de3662e460
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
|
@ -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)";
|
||||
|
@ -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 },
|
||||
|
@ -94,6 +94,8 @@ enum {
|
||||
LOCK_XSYN_EXCL,
|
||||
LOCK_EXCL_XSYN,
|
||||
LOCK_XSYN_SYNC,
|
||||
LOCK_XSYN_LOCK,
|
||||
LOCK_XSYN_MIX,
|
||||
|
||||
LOCK_MAX,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user