xlist_dirty_dirfrag_dirfragtree(this),
auth_pins(0), nested_auth_pins(0),
nested_anchors(0),
- versionlock(this, CEPH_LOCK_IVERSION),
- authlock(this, CEPH_LOCK_IAUTH),
- linklock(this, CEPH_LOCK_ILINK),
- dirfragtreelock(this, CEPH_LOCK_IDFT),
- filelock(this, CEPH_LOCK_IFILE),
- xattrlock(this, CEPH_LOCK_IXATTR),
- snaplock(this, CEPH_LOCK_ISNAP),
- nestlock(this, CEPH_LOCK_INEST),
+ versionlock(this, &versionlock_type),
+ authlock(this, &authlock_type),
+ linklock(this, &linklock_type),
+ dirfragtreelock(this, &dirfragtreelock_type),
+ filelock(this, &filelock_type),
+ xattrlock(this, &xattrlock_type),
+ snaplock(this, &snaplock_type),
+ nestlock(this, &nestlock_type),
loner_cap(-1), want_loner_cap(-1)
{
g_num_ino++;
// -- locks --
public:
+ static LockType versionlock_type;
+ static LockType authlock_type;
+ static LockType linklock_type;
+ static LockType dirfragtreelock_type;
+ static LockType filelock_type;
+ static LockType xattrlock_type;
+ static LockType snaplock_type;
+ static LockType nestlock_type;
+
LocalLock versionlock;
SimpleLock authlock;
SimpleLock linklock;
}
if (!lock->is_gathering() &&
- (lock->sm->states[next].can_rdlock || !lock->is_rdlocked()) &&
- (lock->sm->states[next].can_wrlock || !lock->is_wrlocked()) &&
- (lock->sm->states[next].can_xlock || !lock->is_xlocked()) &&
- (lock->sm->states[next].can_lease || !lock->is_leased()) &&
+ (lock->get_sm()->states[next].can_rdlock || !lock->is_rdlocked()) &&
+ (lock->get_sm()->states[next].can_wrlock || !lock->is_wrlocked()) &&
+ (lock->get_sm()->states[next].can_xlock || !lock->is_xlocked()) &&
+ (lock->get_sm()->states[next].can_lease || !lock->is_leased()) &&
(!caps || ((~lock->gcaps_allowed(CAP_ANY, next) & other_issued) == 0 &&
(~lock->gcaps_allowed(CAP_LONER, next) & loner_issued) == 0 &&
(~lock->gcaps_allowed(CAP_XLOCKER, next) & xlocker_issued) == 0))) {
dout(7) << "eval_gather finished gather on " << *lock
<< " on " << *lock->get_parent() << dendl;
- if (lock->sm == &sm_filelock) {
+ if (lock->get_sm() == &sm_filelock) {
if (in->state_test(CInode::STATE_NEEDSRECOVER)) {
dout(7) << "eval_gather finished gather, but need to recover" << dendl;
mds->mdcache->queue_file_recover(in);
// kick the lock
if (lock->is_stable() &&
lock->get_parent()->is_auth()) {
- if (lock->sm == &sm_scatterlock) {
+ if (lock->get_sm() == &sm_scatterlock) {
if (lock->get_parent()->is_replicated())
scatter_tempsync((ScatterLock*)lock);
else
return false;
} else {
// replica
- assert(lock->sm->can_remote_xlock);
+ assert(lock->get_sm()->can_remote_xlock);
assert(!mut->slave_request);
// wait for single auth
// remote xlock?
if (!lock->get_parent()->is_auth()) {
- assert(lock->sm->can_remote_xlock);
+ assert(lock->get_sm()->can_remote_xlock);
// tell auth
dout(7) << "xlock_finish releasing remote xlock on " << *lock->get_parent() << dendl;
int gather = 0;
if (lock->get_parent()->is_replicated() &&
- lock->sm->states[old_state].replica_state != LOCK_LOCK) { // replica may already be LOCK
+ lock->get_sm()->states[old_state].replica_state != LOCK_LOCK) { // replica may already be LOCK
gather++;
send_lock_message(lock, LOCK_AC_LOCK);
lock->init_gather();
int gather = 0;
if (in->is_replicated() &&
- lock->sm->states[oldstate].replica_state != LOCK_LOCK) {
+ lock->get_sm()->states[oldstate].replica_state != LOCK_LOCK) {
send_lock_message(lock, LOCK_AC_LOCK);
lock->init_gather();
gather++;
#define CAP_LONER 1
#define CAP_XLOCKER 2
+struct LockType {
+ int type;
+ sm_t *sm;
+
+ LockType(int t) : type(t) {
+ switch (type) {
+ case CEPH_LOCK_DN:
+ case CEPH_LOCK_IAUTH:
+ case CEPH_LOCK_ILINK:
+ case CEPH_LOCK_IXATTR:
+ case CEPH_LOCK_ISNAP:
+ sm = &sm_simplelock;
+ break;
+ case CEPH_LOCK_IDFT:
+ case CEPH_LOCK_INEST:
+ sm = &sm_scatterlock;
+ break;
+ case CEPH_LOCK_IFILE:
+ sm = &sm_filelock;
+ break;
+ default:
+ sm = 0;
+ }
+ }
+
+};
+
class SimpleLock {
public:
+ LockType *type;
virtual const char *get_state_name(int n) {
switch (n) {
static const __u64 WAIT_ALL = ((1<<WAIT_BITS)-1);
- sm_t *sm;
-
protected:
// parent (what i lock)
MDSCacheObject *parent;
- int type;
-
- int get_wait_shift() {
- switch (type) {
- case CEPH_LOCK_DN: return 8;
- case CEPH_LOCK_IAUTH: return 5 + SimpleLock::WAIT_BITS;
- case CEPH_LOCK_ILINK: return 5 + SimpleLock::WAIT_BITS;
- case CEPH_LOCK_IDFT: return 5 + 2*SimpleLock::WAIT_BITS;
- case CEPH_LOCK_IFILE: return 5 + 3*SimpleLock::WAIT_BITS;
- case CEPH_LOCK_IVERSION: return 5 + 4*SimpleLock::WAIT_BITS;
- case CEPH_LOCK_IXATTR: return 5 + 5*SimpleLock::WAIT_BITS;
- case CEPH_LOCK_ISNAP: return 5 + 6*SimpleLock::WAIT_BITS;
- case CEPH_LOCK_INEST: return 5 + 7*SimpleLock::WAIT_BITS;
- default:
- assert(0);
- }
- }
// lock state
__s32 state;
public:
- SimpleLock(MDSCacheObject *o, int t) :
- parent(o), type(t),
+ SimpleLock(MDSCacheObject *o, LockType *lt) :
+ type(lt),
+ parent(o),
state(LOCK_SYNC), num_client_lease(0),
num_rdlock(0), num_wrlock(0), num_xlock(0),
xlock_by(0), xlock_by_client(-1), excl_client(-1) {
- switch (type) {
- case CEPH_LOCK_DN:
- case CEPH_LOCK_IAUTH:
- case CEPH_LOCK_ILINK:
- case CEPH_LOCK_IXATTR:
- case CEPH_LOCK_ISNAP:
- sm = &sm_simplelock;
- break;
- case CEPH_LOCK_IDFT:
- case CEPH_LOCK_INEST:
- sm = &sm_scatterlock;
- break;
- case CEPH_LOCK_IFILE:
- sm = &sm_filelock;
- break;
- default:
- sm = 0;
- }
}
virtual ~SimpleLock() {}
// parent
MDSCacheObject *get_parent() { return parent; }
- int get_type() { return type; }
+ int get_type() { return type->type; }
+ const sm_t* get_sm() const { return type->sm; }
+
+ int get_wait_shift() {
+ switch (get_type()) {
+ case CEPH_LOCK_DN: return 8;
+ case CEPH_LOCK_IAUTH: return 5 + SimpleLock::WAIT_BITS;
+ case CEPH_LOCK_ILINK: return 5 + SimpleLock::WAIT_BITS;
+ case CEPH_LOCK_IDFT: return 5 + 2*SimpleLock::WAIT_BITS;
+ case CEPH_LOCK_IFILE: return 5 + 3*SimpleLock::WAIT_BITS;
+ case CEPH_LOCK_IVERSION: return 5 + 4*SimpleLock::WAIT_BITS;
+ case CEPH_LOCK_IXATTR: return 5 + 5*SimpleLock::WAIT_BITS;
+ case CEPH_LOCK_ISNAP: return 5 + 6*SimpleLock::WAIT_BITS;
+ case CEPH_LOCK_INEST: return 5 + 7*SimpleLock::WAIT_BITS;
+ default:
+ assert(0);
+ }
+ }
int get_cap_shift() {
- switch (type) {
+ switch (get_type()) {
case CEPH_LOCK_IAUTH: return CEPH_CAP_SAUTH;
case CEPH_LOCK_ILINK: return CEPH_CAP_SLINK;
case CEPH_LOCK_IFILE: return CEPH_CAP_SFILE;
}
}
int get_cap_mask() {
- switch (type) {
+ switch (get_type()) {
case CEPH_LOCK_IFILE: return 0xffff;
default: return 0x3;
}
struct ptr_lt {
bool operator()(const SimpleLock* l, const SimpleLock* r) const {
// first sort by object type (dn < inode)
- if ((l->type>CEPH_LOCK_DN) < (r->type>CEPH_LOCK_DN)) return true;
- if ((l->type>CEPH_LOCK_DN) == (r->type>CEPH_LOCK_DN)) {
+ if ((l->type->type>CEPH_LOCK_DN) < (r->type->type>CEPH_LOCK_DN)) return true;
+ if ((l->type->type>CEPH_LOCK_DN) == (r->type->type>CEPH_LOCK_DN)) {
// then sort by object
if (l->parent->is_lt(r->parent)) return true;
if (l->parent == r->parent) {
// then sort by (inode) lock type
- if (l->type < r->type) return true;
+ if (l->type->type < r->type->type) return true;
}
}
return false;
};
void decode_locked_state(bufferlist& bl) {
- parent->decode_lock_state(type, bl);
+ parent->decode_lock_state(type->type, bl);
}
void encode_locked_state(bufferlist& bl) {
- parent->encode_lock_state(type, bl);
+ parent->encode_lock_state(type->type, bl);
}
void finish_waiters(__u64 mask, int r=0) {
parent->finish_waiting(mask << get_wait_shift(), r);
}
bool is_stable() {
- return !sm || sm->states[state].next == 0;
+ return !get_sm() || get_sm()->states[state].next == 0;
}
int get_next_state() {
- return sm->states[state].next;
+ return get_sm()->states[state].next;
}
bool fw_rdlock_to_auth() {
- return sm->states[state].can_rdlock == FW;
+ return get_sm()->states[state].can_rdlock == FW;
}
// gather set
// can_*
bool can_lease(client_t client) {
- return sm->states[state].can_lease == ANY ||
- (sm->states[state].can_lease == AUTH && parent->is_auth()) ||
- (sm->states[state].can_lease == XCL && client >= 0 && xlock_by_client == client);
+ return get_sm()->states[state].can_lease == ANY ||
+ (get_sm()->states[state].can_lease == AUTH && parent->is_auth()) ||
+ (get_sm()->states[state].can_lease == XCL && client >= 0 && xlock_by_client == client);
}
bool can_read(client_t client) {
- return sm->states[state].can_read == ANY ||
- (sm->states[state].can_read == AUTH && parent->is_auth()) ||
- (sm->states[state].can_read == XCL && client >= 0 && xlock_by_client == client);
+ return get_sm()->states[state].can_read == ANY ||
+ (get_sm()->states[state].can_read == AUTH && parent->is_auth()) ||
+ (get_sm()->states[state].can_read == XCL && client >= 0 && xlock_by_client == client);
}
bool can_read_projected(client_t client) {
- return sm->states[state].can_read_projected == ANY ||
- (sm->states[state].can_read_projected == AUTH && parent->is_auth()) ||
- (sm->states[state].can_read_projected == XCL && client >= 0 && xlock_by_client == client);
+ return get_sm()->states[state].can_read_projected == ANY ||
+ (get_sm()->states[state].can_read_projected == AUTH && parent->is_auth()) ||
+ (get_sm()->states[state].can_read_projected == XCL && client >= 0 && xlock_by_client == client);
}
bool can_rdlock(client_t client) {
- return sm->states[state].can_rdlock == ANY ||
- (sm->states[state].can_rdlock == AUTH && parent->is_auth()) ||
- (sm->states[state].can_rdlock == XCL && client >= 0 && xlock_by_client == client);
+ return get_sm()->states[state].can_rdlock == ANY ||
+ (get_sm()->states[state].can_rdlock == AUTH && parent->is_auth()) ||
+ (get_sm()->states[state].can_rdlock == XCL && client >= 0 && xlock_by_client == client);
}
bool can_wrlock(client_t client) {
- return sm->states[state].can_wrlock == ANY ||
- (sm->states[state].can_wrlock == AUTH && parent->is_auth()) ||
- (sm->states[state].can_wrlock == XCL && client >= 0 && (xlock_by_client == client ||
+ return get_sm()->states[state].can_wrlock == ANY ||
+ (get_sm()->states[state].can_wrlock == AUTH && parent->is_auth()) ||
+ (get_sm()->states[state].can_wrlock == XCL && client >= 0 && (xlock_by_client == client ||
excl_client == client));
}
bool can_xlock(client_t client) {
- return sm->states[state].can_xlock == ANY ||
- (sm->states[state].can_xlock == AUTH && parent->is_auth()) ||
- (sm->states[state].can_xlock == XCL && client >= 0 && xlock_by_client == client);
+ return get_sm()->states[state].can_xlock == ANY ||
+ (get_sm()->states[state].can_xlock == AUTH && parent->is_auth()) ||
+ (get_sm()->states[state].can_xlock == XCL && client >= 0 && xlock_by_client == client);
}
// rdlock
// caps
bool is_loner_mode() {
- return sm->states[state].loner;
+ return get_sm()->states[state].loner;
}
int gcaps_allowed_ever() {
- return parent->is_auth() ? sm->allowed_ever_auth : sm->allowed_ever_replica;
+ return parent->is_auth() ? get_sm()->allowed_ever_auth : get_sm()->allowed_ever_replica;
}
int gcaps_allowed(int who, int s=-1) {
if (s < 0) s = state;
if (parent->is_auth()) {
if (xlock_by_client >= 0 && who == CAP_XLOCKER)
- return sm->states[s].xlocker_caps;
+ return get_sm()->states[s].xlocker_caps;
else if (is_loner_mode() && who == CAP_ANY)
- return sm->states[s].caps;
+ return get_sm()->states[s].caps;
else
- return sm->states[s].loner_caps | sm->states[s].caps; // loner always gets more
+ return get_sm()->states[s].loner_caps | get_sm()->states[s].caps; // loner always gets more
} else
- return sm->states[s].replica_caps;
+ return get_sm()->states[s].replica_caps;
}
int gcaps_careful() {
if (num_wrlock)
- return sm->careful;
+ return get_sm()->careful;
return 0;
}
int gcaps_xlocker_mask(client_t client) {
if (client == xlock_by_client)
- return type == CEPH_LOCK_IFILE ? 0xffff : (CEPH_CAP_GSHARED|CEPH_CAP_GEXCL);
+ return type->type == CEPH_LOCK_IFILE ? 0xffff : (CEPH_CAP_GSHARED|CEPH_CAP_GEXCL);
return 0;
}
// simplelock specifics
int get_replica_state() const {
- return sm->states[state].replica_state;
+ return get_sm()->states[state].replica_state;
}
void export_twiddle() {
clear_gather();