#include "include/buffer.h"
#include "SimpleLock.h"
+#include "ScatterLock.h"
// states and such.
// C = cache reads, R = read, W = write, A = append, B = buffer writes, L = lazyio
#define LOCK_SYNC_ 1 // AR R . / C R . . . L R . / C R . . . L stat()
#define LOCK_LONER_SYNC -12 // A . . / C r . . . L * loner -> sync
#define LOCK_MIXED_SYNC -13 // A . w / . R . . . L . w / . R . . . L
-#define LOCK_LOCK_SYNC -14 // A . w / C . . . b L
+#define LOCK_LOCK_SYNC_ -14 // A . w / C . . . b L
#define LOCK_LOCK_ 2 // AR R W / C . . . B . . . / C . . . . . truncate()
#define LOCK_SYNC_LOCK_ -3 // AR R . / C . . . . . r . / C . . . . .
*/
-// -- lock... hard or file
class Mutation;
-class FileLock : public SimpleLock {
- int num_wrlock;
-
+class FileLock : public ScatterLock {
public:
FileLock(MDSCacheObject *o, int t, int wo) :
- SimpleLock(o, t, wo),
- num_wrlock(0) { }
+ ScatterLock(o, t, wo) {}
int get_replica_state() const {
switch (state) {
case LOCK_SYNC_MIXED:
return LOCK_MIXED;
case LOCK_SYNC:
+ case LOCK_LOCK_SYNC:
return LOCK_SYNC;
// after gather auth will bc LOCK_AC_MIXED or whatever
state = get_replica_state();
}
+
// read/write access
- bool can_rdlock(Mutation *mdr) {
+ bool can_rdlock() {
if (!parent->is_auth()) {
if (state == LOCK_LOCK && !xlock_by)
return true;
else
return (state == LOCK_MIXED);
}
- void get_wrlock(bool force) {
- assert(force || can_wrlock());
- if (num_wrlock == 0) parent->get(MDSCacheObject::PIN_LOCK);
- ++num_wrlock;
- }
- void put_wrlock() {
- --num_wrlock;
- if (num_wrlock == 0) parent->put(MDSCacheObject::PIN_LOCK);
- }
- bool is_wrlocked() { return num_wrlock > 0; }
- int get_num_wrlocks() { return num_wrlock; }
// client caps allowed
scatter_sync(lock);
// can rdlock?
- if (lock->can_rdlock(mut)) {
+ if (lock->can_rdlock()) {
lock->get_rdlock();
mut->rdlocks.insert(lock);
mut->locks.insert(lock);
}
// gSyncL -> sync?
- else if (lock->get_state() == LOCK_LONER_SYNC &&
+ else if (lock->get_state() == LOCK_LOCK_SYNC &&
!lock->is_wrlocked()) {
dout(7) << "scatter_eval finished sync un-wrlock on " << *lock
<< " on " << *lock->get_parent() << dendl;
if (in->is_base()) {
dout(10) << "scatter_writebehind just clearing updated flag for base inode " << *in << dendl;
lock->clear_updated();
- scatter_eval_gather(lock);
+ eval_gather(lock);
return;
}
case LOCK_LOCK:
if (lock->is_wrlocked() || lock->is_xlocked()) {
- lock->set_state(LOCK_LONER_SYNC);
+ lock->set_state(LOCK_LOCK_SYNC);
lock->get_parent()->auth_pin(lock);
return;
}
dout(7) << "file_rdlock_start " << *lock << " on " << *lock->get_parent() << dendl;
// can read? grab ref.
- if (lock->can_rdlock(mut)) {
+ if (lock->can_rdlock()) {
lock->get_rdlock();
mut->rdlocks.insert(lock);
mut->locks.insert(lock);
if (lock->is_stable()) {
file_lock(lock); // lock, bc easiest to back off ... FIXME
- if (lock->can_rdlock(mut)) {
+ if (lock->can_rdlock()) {
lock->get_rdlock();
mut->rdlocks.insert(lock);
mut->locks.insert(lock);
switch (lock->get_state()) {
// to lock
- case LOCK_SYNC_LOCK:
case LOCK_MIXED_LOCK:
+ if (lock->is_updated()) {
+ scatter_writebehind(lock);
+ return;
+ }
+
+ case LOCK_SYNC_LOCK:
case LOCK_LONER_LOCK:
lock->set_state(LOCK_LOCK);
in->loner_cap = -1;
break;
// to loner
- case LOCK_SYNC_LONER:
case LOCK_MIXED_LONER:
+ if (lock->is_updated()) {
+ scatter_writebehind(lock);
+ return;
+ }
+
+ case LOCK_SYNC_LONER:
case LOCK_LOCK_LONER:
lock->set_state(LOCK_LONER);
lock->finish_waiters(SimpleLock::WAIT_STABLE);
// to sync
case LOCK_MIXED_SYNC:
+ if (lock->is_updated()) {
+ scatter_writebehind(lock);
+ return;
+ }
+
case LOCK_LONER_SYNC:
case LOCK_LOCK_SYNC:
lock->set_state(LOCK_SYNC);
mds->mdcache->do_file_recover();
gather++;
}
+ if (lock->is_updated()) {
+ scatter_writebehind(lock);
+ gather++;
+ }
if (gather)
lock->get_parent()->auth_pin(lock);
bool file_xlock_start(FileLock *lock, MDRequest *mut);
void file_xlock_finish(FileLock *lock, Mutation *mut);
-
+ xlist<FileLock*> updated_filelocks;
+public:
+ void mark_updated_Filelock(FileLock *lock);
// -- file i/o --
public:
dout(10) << "predirty_journal_parents stop. marking nestlock on " << *pin << dendl;
mds->locker->mark_updated_scatterlock(&pin->nestlock);
mut->ls->dirty_dirfrag_nest.push_back(&pin->xlist_dirty_dirfrag_nest);
- mut->add_updated_scatterlock(&pin->nestlock);
+ mut->add_updated_lock(&pin->nestlock);
break;
}
mds->locker->local_wrlock_grab(&pin->versionlock, mut);
// dft lock
mds->locker->mark_updated_scatterlock(&diri->dirfragtreelock);
mdr->ls->dirty_dirfrag_dirfragtree.push_back(&diri->xlist_dirty_dirfrag_dirfragtree);
- mdr->add_updated_scatterlock(&diri->dirfragtreelock);
+ mdr->add_updated_lock(&diri->dirfragtreelock);
// dirlock
mds->locker->mark_updated_scatterlock(&diri->dirlock);
mdr->ls->dirty_dirfrag_dir.push_back(&diri->xlist_dirty_dirfrag_dir);
- mdr->add_updated_scatterlock(&diri->dirlock);
+ mdr->add_updated_lock(&diri->dirlock);
// dirlock
mds->locker->mark_updated_scatterlock(&diri->nestlock);
mdr->ls->dirty_dirfrag_nest.push_back(&diri->xlist_dirty_dirfrag_nest);
- mdr->add_updated_scatterlock(&diri->nestlock);
+ mdr->add_updated_lock(&diri->nestlock);
// journal new dirfrag fragstats for each new fragment.
for (list<CDir*>::iterator p = resultfrags.begin();
// for applying projected inode changes
list<CInode*> projected_inodes;
list<CDir*> projected_fnodes;
- list<ScatterLock*> updated_scatterlocks;
+ list<ScatterLock*> updated_locks;
list<CInode*> dirty_cow_inodes;
list<CDentry*> dirty_cow_dentries;
}
}
- void add_updated_scatterlock(ScatterLock *lock) {
- updated_scatterlocks.push_back(lock);
+ void add_updated_lock(ScatterLock *lock) {
+ updated_locks.push_back(lock);
}
void add_cow_inode(CInode *in) {
p++)
(*p)->_mark_dirty(ls);
- for (list<ScatterLock*>::iterator p = updated_scatterlocks.begin();
- p != updated_scatterlocks.end();
+ for (list<ScatterLock*>::iterator p = updated_locks.begin();
+ p != updated_locks.end();
p++)
(*p)->set_updated();
}
#define LOCK_SYNC_LOCK__ -20 // r . r . waiting for replicas+rdlocks (auth), or rdlocks to release (replica)
#define LOCK_SYNC_SCATTER -28 // r . r .
-#define LOCK_LOCK_SYNC__ // . w LOCK on replica.
+#define LOCK_LOCK_SYNC -29 // . w LOCK on replica.
#define LOCK_LOCK__ // . W . .
#define LOCK_LOCK_TEMPSYNC -21 // . w LOCK on replica.
case LOCK_SYNC_LOCK: return "sync->lock";
case LOCK_SYNC_SCATTER: return "sync->scatter";
- case LOCK_LONER_SYNC: return "loner->sync";
+ case LOCK_LOCK_SYNC: return "lock->sync";
case LOCK_LOCK: return "lock";
case LOCK_LOCK_TEMPSYNC: return "lock->tempsync";
}
class ScatterLock : public SimpleLock {
- int num_wrlock;
bool updated;
utime_t last_scatter;
ScatterLock(MDSCacheObject *o, int t, int wo) :
SimpleLock(o, t, wo),
- num_wrlock(0),
updated(false),
xlistitem_updated(this) {}
~ScatterLock() {
case LOCK_SYNC_SCATTER: // hrm.
case LOCK_SYNC_LOCK:
- case LOCK_LONER_SYNC:
+ case LOCK_LOCK_SYNC:
case LOCK_LOCK:
case LOCK_LOCK_TEMPSYNC:
case LOCK_SCATTER_LOCK:
}
// rdlock
- bool can_rdlock(MDRequest *mdr) {
+ bool can_rdlock() {
return state == LOCK_SYNC || state == LOCK_TEMPSYNC;
}
bool can_rdlock_soon() {
state == LOCK_SCATTER ||
(parent->is_auth() && state == LOCK_LOCK);
}
- void get_wrlock(bool force=false) {
- assert(can_wrlock() || force);
- if (num_wrlock == 0) parent->get(MDSCacheObject::PIN_LOCK);
- ++num_wrlock;
- }
- void put_wrlock() {
- --num_wrlock;
- if (num_wrlock == 0) parent->put(MDSCacheObject::PIN_LOCK);
- }
- bool is_wrlocked() { return num_wrlock > 0; }
- int get_num_wrlocks() { return num_wrlock; }
void print(ostream& out) {
out << "(";
pf->fragstat.mtime = rollback.old_dir_mtime;
if (pf->rstat.rctime == pi->ctime)
pf->rstat.rctime = rollback.old_dir_rctime;
- mut->add_updated_scatterlock(&parent->get_inode()->dirlock);
- mut->add_updated_scatterlock(&parent->get_inode()->nestlock);
+ mut->add_updated_lock(&parent->get_inode()->dirlock);
+ mut->add_updated_lock(&parent->get_inode()->nestlock);
}
// inode
pf->fragstat.mtime = r.dirfrag_old_mtime;
if (pf->rstat.rctime == ctime)
pf->rstat.rctime = r.dirfrag_old_rctime;
- mut->add_updated_scatterlock(&dir->get_inode()->dirlock);
- mut->add_updated_scatterlock(&dir->get_inode()->nestlock);
+ mut->add_updated_lock(&dir->get_inode()->dirlock);
+ mut->add_updated_lock(&dir->get_inode()->nestlock);
}
}
int num_client_lease;
// local state
- int num_rdlock;
+ int num_rdlock, num_wrlock;
Mutation *xlock_by;
SimpleLock(MDSCacheObject *o, int t, int wo) :
parent(o), type(t), wait_offset(wo),
state(LOCK_SYNC), num_client_lease(0),
- num_rdlock(0), xlock_by(0) { }
+ num_rdlock(0), num_wrlock(0), xlock_by(0) { }
virtual ~SimpleLock() {}
// parent
gather_set.erase(i);
}
- // ref counting
+ // rdlock
bool is_rdlocked() { return num_rdlock > 0; }
int get_rdlock() {
if (!num_rdlock) parent->get(MDSCacheObject::PIN_LOCK);
}
int get_num_rdlocks() { return num_rdlock; }
+ // wrlock
+ virtual bool can_wrlock() { return false; }
+ void get_wrlock(bool force=false) {
+ assert(can_wrlock() || force);
+ if (num_wrlock == 0) parent->get(MDSCacheObject::PIN_LOCK);
+ ++num_wrlock;
+ }
+ void put_wrlock() {
+ --num_wrlock;
+ if (num_wrlock == 0) parent->put(MDSCacheObject::PIN_LOCK);
+ }
+ bool is_wrlocked() { return num_wrlock > 0; }
+ int get_num_wrlocks() { return num_wrlock; }
+
+ // xlock
void get_xlock(Mutation *who) {
assert(xlock_by == 0);
parent->get(MDSCacheObject::PIN_LOCK);
}
-
// simplelock specifics
virtual int get_replica_state() const {
switch (state) {