l = client_lease_map[c];
else {
dout(20) << "add_client_lease client." << c << " on " << lock << dendl;
- if (client_lease_map.empty())
+ if (client_lease_map.empty()) {
get(PIN_CLIENTLEASE);
+ lock.get_client_lease();
+ }
l = client_lease_map[c] = new ClientLease(c, this);
l->seq = ++session->lease_seq;
- lock.get_client_lease();
}
return l;
bool gather = false;
dout(20) << "remove_client_lease client." << l->client << " on " << lock << dendl;
- lock.put_client_lease();
- if (lock.get_num_client_lease() == 0 && !lock.is_stable())
- gather = true;
client_lease_map.erase(l->client);
l->item_lease.remove_myself();
l->item_session_lease.remove_myself();
delete l;
- if (client_lease_map.empty())
+ if (client_lease_map.empty()) {
+ gather = !lock.is_stable();
+ lock.put_client_lease();
put(PIN_CLIENTLEASE);
+ }
if (gather)
locker->eval_gather(&lock);
assert(!lock->is_stable());
if (lock->get_num_rdlocks() == 0 &&
lock->get_num_wrlocks() == 0 &&
- lock->get_num_client_lease() == 0 &&
+ !lock->is_leased() &&
lock->get_state() != LOCK_XLOCKSNAP &&
lock->get_type() != CEPH_LOCK_DN) {
CInode *in = static_cast<CInode*>(lock->get_parent());
dn->get_name()),
l->client);
}
- assert(n == lock->get_num_client_lease());
}
dout(10) << "scatter_nudge waiting for unfreeze on " << *p << dendl;
if (c)
p->add_waiter(MDSCacheObject::WAIT_UNFREEZE, c);
- else
+ else if (lock->is_dirty())
// just requeue. not ideal.. starvation prone..
updated_scatterlocks.push_back(lock->get_updated_item());
return;
dout(10) << "scatter_nudge waiting for single auth on " << *p << dendl;
if (c)
p->add_waiter(MDSCacheObject::WAIT_SINGLEAUTH, c);
- else
+ else if (lock->is_dirty())
// just requeue. not ideal.. starvation prone..
updated_scatterlocks.push_back(lock->get_updated_item());
return;
lock->add_waiter(SimpleLock::WAIT_STABLE, c);
// also, requeue, in case we had wrong auth or something
- updated_scatterlocks.push_back(lock->get_updated_item());
+ if (lock->is_dirty())
+ updated_scatterlocks.push_back(lock->get_updated_item());
}
}
in->is_dir() && in->has_subtree_or_exporting_dirfrag()) // if we are a delegation point, stay where we are
//((wanted & CEPH_CAP_RD) ||
//in->is_replicated() ||
- //lock->get_num_client_lease() ||
+ //lock->is_leased() ||
//(!loner && lock->get_state() == LOCK_EXCL)) &&
) {
dout(7) << "file_eval stable, bump to sync " << *lock
class ScatterLock : public SimpleLock {
struct more_bits_t {
- int state_flags;
- utime_t last_scatter;
xlist<ScatterLock*>::item item_updated;
utime_t update_stamp;
explicit more_bits_t(ScatterLock *lock) :
- state_flags(0),
item_updated(lock)
{}
-
- bool empty() const {
- return
- !state_flags &&
- !item_updated.is_on_list();
- }
};
- more_bits_t *_more;
- bool have_more() const { return _more ? true : false; }
- void try_clear_more() {
- if (_more && _more->empty()) {
- delete _more;
- _more = NULL;
- }
- }
+ mutable std::unique_ptr<more_bits_t> _more;
+
more_bits_t *more() {
if (!_more)
- _more = new more_bits_t(this);
- return _more;
+ _more.reset(new more_bits_t(this));
+ return _more.get();
}
- enum flag_values { // flag values for more_bits_t state
- SCATTER_WANTED = 1 << 0,
- UNSCATTER_WANTED = 1 << 1,
- DIRTY = 1 << 2,
- FLUSHING = 1 << 3,
- FLUSHED = 1 << 4,
- REJOIN_MIX = 1 << 5, // no rdlock until the recovering mds become active
+ enum {
+ SCATTER_WANTED = 1 << 8,
+ UNSCATTER_WANTED = 1 << 9,
+ DIRTY = 1 << 10,
+ FLUSHING = 1 << 11,
+ FLUSHED = 1 << 12,
+ REJOIN_MIX = 1 << 13,
};
public:
- ScatterLock(MDSCacheObject *o, LockType *lt) :
- SimpleLock(o, lt), _more(NULL)
- {}
+ ScatterLock(MDSCacheObject *o, LockType *lt) :
+ SimpleLock(o, lt) {}
~ScatterLock() override {
- if (_more) {
- _more->item_updated.remove_myself(); // FIXME this should happen sooner, i think...
- delete _more;
- }
+ assert(!_more);
}
bool is_scatterlock() const override {
xlist<ScatterLock*>::item *get_updated_item() { return &more()->item_updated; }
utime_t get_update_stamp() {
- return more()->update_stamp;
+ return _more ? _more->update_stamp : utime_t();
}
void set_update_stamp(utime_t t) { more()->update_stamp = t; }
void set_scatter_wanted() {
- more()->state_flags |= SCATTER_WANTED;
+ state_flags |= SCATTER_WANTED;
}
void set_unscatter_wanted() {
- more()->state_flags |= UNSCATTER_WANTED;
+ state_flags |= UNSCATTER_WANTED;
}
void clear_scatter_wanted() {
- if (have_more())
- _more->state_flags &= ~SCATTER_WANTED;
- try_clear_more();
+ state_flags &= ~SCATTER_WANTED;
}
void clear_unscatter_wanted() {
- if (have_more())
- _more->state_flags &= ~UNSCATTER_WANTED;
- try_clear_more();
+ state_flags &= ~UNSCATTER_WANTED;
}
bool get_scatter_wanted() const {
- return have_more() ? _more->state_flags & SCATTER_WANTED : false;
+ return state_flags & SCATTER_WANTED;
}
bool get_unscatter_wanted() const {
- return have_more() ? _more->state_flags & UNSCATTER_WANTED : false;
+ return state_flags & UNSCATTER_WANTED;
}
bool is_dirty() const override {
- return have_more() ? _more->state_flags & DIRTY : false;
+ return state_flags & DIRTY;
}
bool is_flushing() const override {
- return have_more() ? _more->state_flags & FLUSHING: false;
+ return state_flags & FLUSHING;
}
bool is_flushed() const override {
- return have_more() ? _more->state_flags & FLUSHED: false;
+ return state_flags & FLUSHED;
}
bool is_dirty_or_flushing() const {
- return have_more() ? (is_dirty() || is_flushing()) : false;
+ return is_dirty() || is_flushing();
}
bool is_rejoin_mix() const {
- return have_more() ? _more->state_flags & REJOIN_MIX : false;
+ return state_flags & REJOIN_MIX;
}
void mark_dirty() {
finish_flush();
}
void clear_flushed() override {
- if (have_more()) {
- _more->state_flags &= ~FLUSHED;
- try_clear_more();
- }
+ state_flags &= ~FLUSHED;
}
-
void clear_rejoin_mix() {
- if (have_more()) {
- _more->state_flags &= ~REJOIN_MIX;
- try_clear_more();
- }
- }
-
- void set_last_scatter(utime_t t) { more()->last_scatter = t; }
- utime_t get_last_scatter() {
- return more()->last_scatter;
+ state_flags &= ~REJOIN_MIX;
}
void infer_state_from_strong_rejoin(int rstate, bool locktoo) {
}
if (s == LOCK_MIX || s == LOCK_MIX_LOCK || s == LOCK_MIX_SYNC)
- more()->state_flags |= REJOIN_MIX;
+ state_flags |= REJOIN_MIX;
::encode(s, bl);
}
private:
void set_flushing() {
- more()->state_flags |= FLUSHING;
+ state_flags |= FLUSHING;
}
void clear_flushing() {
- if (have_more()) {
- _more->state_flags &= ~FLUSHING;
- }
+ state_flags &= ~FLUSHING;
}
void set_flushed() {
- more()->state_flags |= FLUSHED;
+ state_flags |= FLUSHED;
}
void set_dirty() {
- more()->state_flags |= DIRTY;
+ state_flags |= DIRTY;
}
void clear_dirty() {
- if (have_more()) {
- _more->state_flags &= ~DIRTY;
+ state_flags &= ~DIRTY;
+ if (_more) {
+ _more->item_updated.remove_myself();
+ _more.reset();
}
}
};
// lock state
__s16 state;
+ __s16 state_flags;
+
+ enum {
+ LEASED = 1 << 0,
+ };
private:
- __s16 num_rdlock;
- __s32 num_client_lease;
+ int num_rdlock;
struct unstable_bits_t {
set<__s32> gather_set; // auth+rep. >= 0 is mds, < 0 is client
type(lt),
parent(o),
state(LOCK_SYNC),
- num_rdlock(0),
- num_client_lease(0)
+ state_flags(0),
+ num_rdlock(0)
{}
virtual ~SimpleLock() {}
}
// lease
+ bool is_leased() const {
+ return state_flags & LEASED;
+ }
void get_client_lease() {
- num_client_lease++;
+ assert(!is_leased());
+ state_flags |= LEASED;
}
void put_client_lease() {
- assert(num_client_lease > 0);
- num_client_lease--;
- if (num_client_lease == 0) {
- try_clear_more();
- }
- }
- bool is_leased() const {
- return num_client_lease > 0;
- }
- int get_num_client_lease() const {
- return num_client_lease;
+ assert(is_leased());
+ state_flags &= ~LEASED;
}
bool is_used() const {
- return is_xlocked() || is_rdlocked() || is_wrlocked() || num_client_lease;
+ return is_xlocked() || is_rdlocked() || is_wrlocked() || is_leased();
}
// encode/decode
out << get_state_name(get_state());
if (!get_gather_set().empty())
out << " g=" << get_gather_set();
- if (num_client_lease)
- out << " l=" << num_client_lease;
+ if (is_leased())
+ out << " l";
if (is_rdlocked())
out << " r=" << get_num_rdlocks();
if (is_wrlocked())