send_lock_message(lock, LOCK_AC_MIX, softdata);
}
break;
-
+
+ // to sync
case LOCK_EXCL_SYNC:
case LOCK_LOCK_SYNC:
- { // bcast data to replicas
+ case LOCK_MIX_SYNC:
+ if (in->is_replicated()) {
bufferlist softdata;
lock->encode_locked_state(softdata);
send_lock_message(lock, LOCK_AC_SYNC, softdata);
if (in->is_auth()) {
if (want_scatter) {
- if (lock->sm == &sm_filelock)
- file_mixed((ScatterLock*)lock);
- else
- scatter_scatter((ScatterLock*)lock, nowait);
+ file_mixed((ScatterLock*)lock);
} else
simple_lock(lock);
handle_simple_lock(lock, m);
break;
+ case CEPH_LOCK_IDFT:
+ case CEPH_LOCK_INEST:
+ //handle_scatter_lock((ScatterLock*)lock, m);
+ //break;
+
case CEPH_LOCK_IFILE:
handle_file_lock((ScatterLock*)lock, m);
break;
- case CEPH_LOCK_IDFT:
- case CEPH_LOCK_INEST:
- handle_scatter_lock((ScatterLock*)lock, m);
- break;
-
default:
dout(7) << "handle_lock got otype " << m->get_lock_type() << dendl;
assert(0);
if (lock->get_parent()->is_frozen()) return;
- if (lock->get_type() == CEPH_LOCK_INEST &&
- !lock->is_rdlocked() &&
- lock->get_state() != LOCK_MIX) {
- scatter_scatter(lock);
- return;
+ if (lock->get_type() == CEPH_LOCK_INEST) {
+ // in general, we want to keep INEST scattered at all times.
+ if (!lock->is_rdlocked() &&
+ lock->get_state() != LOCK_MIX)
+ file_mixed(lock);
+ return;
}
CInode *in = (CInode*)lock->get_parent();
case CEPH_LOCK_IDFT:
case CEPH_LOCK_INEST:
if (p->is_replicated() && lock->get_state() != LOCK_MIX)
- scatter_scatter(lock);
+ file_mixed(lock);
else // if (lock->get_state() != LOCK_LOCK)
simple_lock(lock);
//else
}
-
-bool Locker::scatter_scatter_fastpath(ScatterLock *lock)
-{
- assert(lock->get_parent()->is_auth());
- assert(lock->is_stable());
-
- if (lock->get_state() == LOCK_MIX)
- return true;
- if (!lock->is_rdlocked() &&
- !lock->is_xlocked() &&
- !lock->get_num_client_lease() &&
- (!lock->get_parent()->is_replicated() || // if sync
- lock->get_state() == LOCK_LOCK ||
- lock->get_state() == LOCK_TSYN)) {
- dout(10) << "scatter_scatter_fastpath YES " << *lock
- << " on " << *lock->get_parent() << dendl;
- // do scatter
- lock->set_last_scatter(g_clock.now());
-
- if (lock->get_parent()->is_replicated()) {
- // encode and bcast
- bufferlist data;
- lock->encode_locked_state(data);
- send_lock_message(lock, LOCK_AC_MIX, data);
- }
-
- ((CInode *)lock->get_parent())->try_drop_loner();
-
- lock->set_state(LOCK_MIX);
- lock->finish_waiters(ScatterLock::WAIT_WR|ScatterLock::WAIT_STABLE);
- return true;
- }
- dout(20) << "scatter_scatter_fastpath NO " << *lock
- << " on " << *lock->get_parent() << dendl;
- return false;
-}
-
-void Locker::scatter_scatter(ScatterLock *lock, bool nowait)
-{
- dout(10) << "scatter_scatter " << *lock
- << " on " << *lock->get_parent() << dendl;
- assert(lock->get_parent()->is_auth());
- assert(lock->is_stable());
-
- if (scatter_scatter_fastpath(lock) || nowait)
- return;
-
- if (lock->is_xlocked())
- return; // do nothing.
-
- switch (lock->get_state()) {
- case LOCK_SYNC: lock->set_state(LOCK_SYNC_MIX); break;
- case LOCK_TSYN: lock->set_state(LOCK_TSYN_MIX); break;
- default: assert(0);
- }
-
- lock->get_parent()->auth_pin(lock);
-
- if (lock->get_parent()->is_replicated()) {
- send_lock_message(lock, LOCK_AC_LOCK);
- lock->init_gather();
- }
- if (lock->get_num_client_lease())
- revoke_client_leases(lock);
-}
-
-
void Locker::scatter_tempsync(ScatterLock *lock)
{
dout(10) << "scatter_tempsync " << *lock
-void Locker::handle_scatter_lock(ScatterLock *lock, MLock *m)
-{
- int from = m->get_asker();
- dout(10) << "handle_scatter_lock " << *m << " on " << *lock << " on " << *lock->get_parent() << dendl;
-
- if (mds->is_rejoin()) {
- if (lock->get_parent()->is_rejoining()) {
- dout(7) << "handle_scatter_lock still rejoining " << *lock->get_parent()
- << ", dropping " << *m << dendl;
- delete m;
- return;
- }
- }
-
- switch (m->get_action()) {
- // -- replica --
- case LOCK_AC_SYNC:
- assert(lock->get_state() == LOCK_LOCK);
- lock->set_state(LOCK_SYNC);
- lock->decode_locked_state(m->get_data());
- lock->clear_updated();
- lock->finish_waiters(ScatterLock::WAIT_RD|ScatterLock::WAIT_STABLE);
- break;
-
- case LOCK_AC_LOCK:
- assert(lock->get_state() == LOCK_MIX ||
- lock->get_state() == LOCK_SYNC);
-
- // wait for wrlocks to close?
- if (lock->is_wrlocked()) {
- assert(lock->get_state() == LOCK_MIX);
- dout(7) << "handle_scatter_lock has wrlocks, waiting on " << *lock
- << " on " << *lock->get_parent() << dendl;
- lock->set_state(LOCK_MIX_LOCK);
- } else if (lock->is_rdlocked() ||
- lock->get_num_client_lease()) {
- assert(lock->get_state() == LOCK_SYNC);
- dout(7) << "handle_scatter_lock has rdlocks|leases, waiting on " << *lock
- << " on " << *lock->get_parent() << dendl;
- revoke_client_leases(lock);
- lock->set_state(LOCK_SYNC_LOCK);
- } else {
- dout(7) << "handle_scatter_lock has no rd|wrlocks|leases, sending lockack for " << *lock
- << " on " << *lock->get_parent() << dendl;
-
- // encode and reply
- bufferlist data;
- lock->encode_locked_state(data);
- mds->send_message_mds(new MLock(lock, LOCK_AC_LOCKACK, mds->get_nodeid(), data), from);
- lock->set_state(LOCK_LOCK);
- }
- break;
-
- case LOCK_AC_MIX:
- assert(lock->get_state() == LOCK_LOCK);
- lock->decode_locked_state(m->get_data());
- lock->clear_updated();
- lock->set_state(LOCK_MIX);
- lock->finish_waiters(ScatterLock::WAIT_WR|ScatterLock::WAIT_STABLE);
- break;
-
- // -- for auth --
- case LOCK_AC_LOCKACK:
- assert(lock->get_state() == LOCK_SYNC_LOCK ||
- lock->get_state() == LOCK_MIX_LOCK ||
- lock->get_state() == LOCK_SYNC_MIX ||
- lock->get_state() == LOCK_MIX_TSYN);
- assert(lock->is_gathering(from));
- lock->remove_gather(from);
- lock->decode_locked_state(m->get_data());
-
- if (lock->is_gathering()) {
- dout(7) << "handle_scatter_lock " << *lock << " on " << *lock->get_parent()
- << " from " << from << ", still gathering " << lock->get_gather_set()
- << dendl;
- } else {
- dout(7) << "handle_scatter_lock " << *lock << " on " << *lock->get_parent()
- << " from " << from << ", last one"
- << dendl;
- eval_gather(lock);
- }
- break;
-
- case LOCK_AC_REQSCATTER:
- if (lock->is_stable()) {
- /* NOTE: we can do this _even_ if !can_auth_pin (i.e. freezing)
- * because the replica should be holding an auth_pin if they're
- * doing this (and thus, we are freezing, not frozen, and indefinite
- * starvation isn't an issue).
- */
- dout(7) << "handle_scatter_lock got scatter request on " << *lock
- << " on " << *lock->get_parent() << dendl;
- scatter_scatter(lock);
- } else {
- dout(7) << "handle_scatter_lock ignoring scatter request on " << *lock
- << " on " << *lock->get_parent() << dendl;
- }
- break;
-
- /*
- case LOCK_AC_REQUNMIX:
- if (!lock->is_stable()) {
- dout(7) << "handle_scatter_lock ignoring now-unnecessary unscatter request on " << *lock
- << " on " << *lock->get_parent() << dendl;
- } else if (lock->get_parent()->can_auth_pin()) {
- dout(7) << "handle_scatter_lock got unscatter request on " << *lock
- << " on " << *lock->get_parent() << dendl;
- scatter_lock(lock);
- } else {
- dout(7) << "handle_scatter_lock DROPPING unscatter request on " << *lock
- << " on " << *lock->get_parent() << dendl;
- // FIXME: if we can't auth_pin here, this request is effectively lost...
- }
- break;
- */
-
- case LOCK_AC_NUDGE:
- if (lock->get_parent()->is_auth()) {
- dout(7) << "handle_scatter_lock trying nudge on " << *lock
- << " on " << *lock->get_parent() << dendl;
- scatter_nudge(lock, 0);
- } else {
- dout(7) << "handle_scatter_lock IGNORING nudge on non-auth " << *lock
- << " on " << *lock->get_parent() << dendl;
- }
- break;
-
- default:
- assert(0);
- }
-
- delete m;
-}
-
-
-
-
-
-
// ==========================================================================
// local lock
switch (lock->get_state()) {
case LOCK_SYNC: lock->set_state(LOCK_SYNC_MIX); break;
case LOCK_EXCL: lock->set_state(LOCK_EXCL_MIX); break;
+ case LOCK_TSYN: lock->set_state(LOCK_TSYN_MIX); break;
default: assert(0);
}
revoke_client_leases(lock);
gather++;
}
- int loner_issued, other_issued;
- in->get_caps_issued(&loner_issued, &other_issued, CEPH_CAP_SFILE);
- if ((loner_issued & ~lock->gcaps_allowed(true)) ||
- (other_issued & ~lock->gcaps_allowed(false))) {
- issue_caps(in);
- gather++;
+ if (lock->get_cap_shift()) {
+ int loner_issued, other_issued;
+ in->get_caps_issued(&loner_issued, &other_issued, lock->get_cap_shift());
+ if ((loner_issued & ~lock->gcaps_allowed(true)) ||
+ (other_issued & ~lock->gcaps_allowed(false))) {
+ issue_caps(in);
+ gather++;
+ }
}
if (in->state_test(CInode::STATE_NEEDSRECOVER)) {
mds->mdcache->queue_file_recover(in);
else {
in->try_drop_loner();
lock->set_state(LOCK_MIX);
- issue_caps(in);
+ if (lock->get_cap_shift())
+ issue_caps(in);
}
}
}
}
}
-
dout(7) << "handle_file_lock a=" << get_lock_action_name(m->get_action())
<< " on " << *lock
<< " from mds" << from << " "
<< *in << dendl;
+
+ bool caps = lock->get_cap_shift();
switch (m->get_action()) {
// -- replica --
// call back caps?
int loner_issued, other_issued;
- in->get_caps_issued(&loner_issued, &other_issued, CEPH_CAP_SFILE);
- if ((loner_issued & ~lock->gcaps_allowed(true)) ||
- (other_issued & ~lock->gcaps_allowed(false))) {
+ if (caps)
+ in->get_caps_issued(&loner_issued, &other_issued, CEPH_CAP_SFILE);
+ if (caps && ((loner_issued & ~lock->gcaps_allowed(true)) ||
+ (other_issued & ~lock->gcaps_allowed(false)))) {
dout(7) << "handle_file_lock client readers, gathering caps on " << *in << dendl;
issue_caps(in);
break;
// no ack needed.
}
- issue_caps(in);
+ if (caps)
+ issue_caps(in);
// waiters
lock->finish_waiters(SimpleLock::WAIT_WR|SimpleLock::WAIT_STABLE);
assert(lock->get_state() == LOCK_SYNC_LOCK ||
lock->get_state() == LOCK_MIX_LOCK ||
lock->get_state() == LOCK_MIX_EXCL ||
- lock->get_state() == LOCK_SYNC_EXCL);
+ lock->get_state() == LOCK_SYNC_EXCL ||
+ lock->get_state() == LOCK_SYNC_MIX ||
+ lock->get_state() == LOCK_MIX_TSYN);
assert(lock->is_gathering(from));
lock->remove_gather(from);
if (lock->get_state() == LOCK_MIX_LOCK ||
- lock->get_state() == LOCK_MIX_EXCL)
+ lock->get_state() == LOCK_MIX_EXCL ||
+ lock->get_state() == LOCK_MIX_TSYN)
lock->decode_locked_state(m->get_data());
if (lock->is_gathering()) {
- dout(7) << "handle_lock_inode_file " << *in << " from " << from
+ dout(7) << "handle_file_lock " << *in << " from " << from
<< ", still gathering " << lock->get_gather_set() << dendl;
} else {
- dout(7) << "handle_lock_inode_file " << *in << " from " << from
+ dout(7) << "handle_file_lock " << *in << " from " << from
<< ", last one" << dendl;
eval_gather(lock);
}
break;
case LOCK_AC_SYNCACK:
- assert(lock->get_state() == LOCK_MIX_SYNC ||
- lock->get_state() == LOCK_MIX_SYNC2);
+ assert(lock->get_state() == LOCK_MIX_SYNC);
assert(lock->is_gathering(from));
lock->remove_gather(from);
lock->decode_locked_state(m->get_data());
if (lock->is_gathering()) {
- dout(7) << "handle_lock_inode_file " << *in << " from " << from
+ dout(7) << "handle_file_lock " << *in << " from " << from
<< ", still gathering " << lock->get_gather_set() << dendl;
} else {
- dout(7) << "handle_lock_inode_file " << *in << " from " << from
+ dout(7) << "handle_file_lock " << *in << " from " << from
<< ", last one" << dendl;
eval_gather(lock);
}
lock->remove_gather(from);
if (lock->is_gathering()) {
- dout(7) << "handle_lock_inode_file " << *in << " from " << from
+ dout(7) << "handle_file_lock " << *in << " from " << from
<< ", still gathering " << lock->get_gather_set() << dendl;
} else {
- dout(7) << "handle_lock_inode_file " << *in << " from " << from
+ dout(7) << "handle_file_lock " << *in << " from " << from
<< ", last one" << dendl;
eval_gather(lock);
}