bool Locker::wrlock_start(SimpleLock *lock, MDRequest *mut)
{
switch (lock->get_type()) {
+ case CEPH_LOCK_IAUTH:
+ return simple_wrlock_start((SimpleLock*)lock, mut);
case CEPH_LOCK_IDFT:
case CEPH_LOCK_INEST:
return scatter_wrlock_start((ScatterLock*)lock, mut);
void Locker::wrlock_finish(SimpleLock *lock, Mutation *mut)
{
switch (lock->get_type()) {
+ case CEPH_LOCK_IAUTH:
+ return simple_wrlock_finish(lock, mut);
case CEPH_LOCK_IDFT:
case CEPH_LOCK_INEST:
return scatter_wrlock_finish((ScatterLock*)lock, mut);
!lock->is_gathering() &&
lock->get_num_client_lease() == 0 &&
!lock->is_rdlocked()) {
- dout(7) << "simple_eval finished gather on " << *lock << " on " << *lock->get_parent() << dendl;
+ dout(7) << "simple_eval finished gather on " << *lock
+ << " on " << *lock->get_parent() << dendl;
// replica: tell auth
if (!lock->get_parent()->is_auth()) {
simple_eval(lock);
}
}
+
+ else if (lock->get_state() == LOCK_LOCK_SYNC &&
+ !lock->is_gathering() &&
+ !lock->is_wrlocked()) {
+ dout(7) << "simple_eval finished gather on " << *lock
+ << " on " << *lock->get_parent() << dendl;
+ assert(lock->get_parent()->is_auth());
+
+ lock->set_state(LOCK_SYNC);
+ lock->finish_waiters(SimpleLock::WAIT_STABLE|SimpleLock::WAIT_RD);
+
+ lock->get_parent()->auth_unpin(lock);
+
+ // re-eval?
+ simple_eval(lock);
+ }
}
void Locker::simple_eval(SimpleLock *lock)
// stable -> sync?
if (!lock->is_xlocked() &&
+ !lock->is_wrlocked() &&
lock->get_state() != LOCK_SYNC &&
!lock->is_waiter_for(SimpleLock::WAIT_WR)) {
dout(7) << "simple_eval stable, syncing " << *lock
<< " on " << *lock->get_parent() << dendl;
simple_sync(lock);
}
-
}
// mid
-void Locker::simple_sync(SimpleLock *lock)
+bool Locker::simple_sync(SimpleLock *lock)
{
dout(7) << "simple_sync on " << *lock << " on " << *lock->get_parent() << dendl;
assert(lock->get_parent()->is_auth());
assert(lock->is_stable());
-
- // check state
- if (lock->get_state() == LOCK_SYNC)
- return; // already sync
+
assert(lock->get_state() == LOCK_LOCK);
+
+ lock->set_state(LOCK_LOCK_SYNC);
+
+ int gather = 0;
+ if (lock->is_wrlocked()) {
+ gather++;
+ }
+
+ if (gather) {
+ lock->get_parent()->auth_pin(lock);
+ return false;
+ }
- // sync.
if (lock->get_parent()->is_replicated()) {
- // hard data
bufferlist data;
lock->encode_locked_state(data);
-
- // bcast to replicas
send_lock_message(lock, LOCK_AC_SYNC, data);
}
-
- // change lock
+
lock->set_state(LOCK_SYNC);
-
- // waiters?
lock->finish_waiters(SimpleLock::WAIT_RD|SimpleLock::WAIT_STABLE);
+ return true;
}
void Locker::simple_lock(SimpleLock *lock)
{
dout(7) << "simple_rdlock_start on " << *lock << " on " << *lock->get_parent() << dendl;
- // can read? grab ref.
- if (lock->can_rdlock(mut)) {
- lock->get_rdlock();
- mut->rdlocks.insert(lock);
- mut->locks.insert(lock);
- return true;
+ while (1) {
+ // can read? grab ref.
+ if (lock->can_rdlock(mut)) {
+ lock->get_rdlock();
+ mut->rdlocks.insert(lock);
+ mut->locks.insert(lock);
+ return true;
+ }
+
+ if (lock->is_stable() &&
+ lock->get_parent()->is_auth())
+ simple_sync(lock);
+ else
+ break;
}
-
+
// wait!
dout(7) << "simple_rdlock_start waiting on " << *lock << " on " << *lock->get_parent() << dendl;
lock->add_waiter(SimpleLock::WAIT_RD, new C_MDS_RetryRequest(mdcache, mut));
return false;
}
+bool Locker::simple_wrlock_start(SimpleLock *lock, MDRequest *mut)
+{
+ dout(7) << "simple_wrlock_start on " << *lock
+ << " on " << *lock->get_parent() << dendl;
+
+ while (1) {
+ // can wrlock?
+ if (lock->can_wrlock()) {
+ lock->get_wrlock();
+ if (mut) {
+ mut->wrlocks.insert(lock);
+ mut->locks.insert(lock);
+ }
+ return true;
+ }
+
+ if (lock->is_stable() && lock->get_state() == LOCK_SYNC)
+ simple_lock(lock);
+ else
+ break;
+ }
+
+ dout(7) << "simple_wrlock_start waiting on " << *lock << " on " << *lock->get_parent() << dendl;
+ lock->add_waiter(SimpleLock::WAIT_STABLE, new C_MDS_RetryRequest(mdcache, mut));
+ return false;
+}
+
+void Locker::simple_wrlock_finish(SimpleLock *lock, Mutation *mut)
+{
+ dout(7) << "simple_wrlock_finish on " << *lock << " on " << *lock->get_parent() << dendl;
+ lock->put_wrlock();
+ if (mut) {
+ mut->wrlocks.erase(lock);
+ mut->locks.erase(lock);
+ }
+
+ if (!lock->is_wrlocked()) {
+ if (!lock->is_stable())
+ simple_eval_gather(lock);
+ else if (lock->get_parent()->is_auth())
+ simple_eval(lock);
+ }
+}
+
void Locker::simple_rdlock_finish(SimpleLock *lock, Mutation *mut)
{
// drop ref
void Locker::file_wrlock_finish(FileLock *lock, Mutation *mut)
{
- dout(7) << "wrlock_finish on " << *lock << " on " << *lock->get_parent() << dendl;
+ dout(7) << "file_wrlock_finish on " << *lock << " on " << *lock->get_parent() << dendl;
lock->put_wrlock();
if (mut) {
mut->wrlocks.erase(lock);
set<SimpleLock*> rdlocks = mdr->rdlocks;
set<SimpleLock*> wrlocks = mdr->wrlocks;
set<SimpleLock*> xlocks = mdr->xlocks;
- xlocks.insert(&cur->authlock);
+ wrlocks.insert(&cur->authlock);
mds->locker->include_snap_rdlocks(rdlocks, cur);
if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
set<SimpleLock*> rdlocks = mdr->rdlocks;
set<SimpleLock*> wrlocks = mdr->wrlocks;
set<SimpleLock*> xlocks = mdr->xlocks;
- xlocks.insert(&cur->authlock);
+ wrlocks.insert(&cur->authlock);
mds->locker->include_snap_rdlocks(rdlocks, cur);
if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
// sync <-> lock
#define LOCK_UNDEF 0
// auth rep
-#define LOCK_SYNC 1 // AR R . R .
-#define LOCK_LOCK 2 // AR R W . .
-#define LOCK_SYNC_LOCK -3 // AR R . . .
-#define LOCK_REMOTEXLOCK -50 // on NON-auth
+#define LOCK_SYNC 1 // AR R . R .
+#define LOCK_LOCK 2 // AR R W . .
+#define LOCK_SYNC_LOCK -3 // AR R . . .
+#define LOCK_LOCK_SYNC -51 // A R w
+#define LOCK_REMOTEXLOCK -50 // on NON-auth
inline const char *get_simplelock_state_name(int n) {
switch (n) {
case LOCK_SYNC: return "sync";
case LOCK_LOCK: return "lock";
case LOCK_SYNC_LOCK: return "sync->lock";
+ case LOCK_LOCK_SYNC: return "lock->sync";
case LOCK_REMOTEXLOCK: return "remote_xlock";
default: assert(0); return 0;
}
int get_num_rdlocks() { return num_rdlock; }
// wrlock
- virtual bool can_wrlock() { return false; }
+ virtual bool can_wrlock() {
+ return state == LOCK_LOCK;
+ }
void get_wrlock(bool force=false) {
assert(can_wrlock() || force);
if (num_wrlock == 0) parent->get(MDSCacheObject::PIN_LOCK);