_pending(0), _issued(0), last_sent(0), last_issue(0), mseq(0),
suppress(0), state(0)
{
+ if (session) {
+ session->touch_cap_bottom(this);
+ }
}
client_t Capability::get_client() const
return session ? session->is_stale() : false;
}
+void Capability::mark_notable()
+{
+ state |= STATE_NOTABLE;
+ session->touch_cap(this);
+}
+
+void Capability::maybe_clear_notable()
+{
+ if ((_issued == _pending) &&
+ !is_clientwriteable() &&
+ !is_wanted_notable(_wanted)) {
+ ceph_assert(is_notable());
+ state &= ~STATE_NOTABLE;
+ session->touch_cap_bottom(this);
+ }
+}
+
+void Capability::set_wanted(int w) {
+ CInode *in = get_inode();
+ if (in) {
+ if (!is_wanted_notable(_wanted) && is_wanted_notable(w)) {
+ if (!is_notable())
+ mark_notable();
+ } else if (is_wanted_notable(_wanted) && !is_wanted_notable(w)) {
+ maybe_clear_notable();
+ }
+ }
+ _wanted = w;
+}
+
void Capability::encode(bufferlist& bl) const
{
ENCODE_START(2, 2, bl)
::decode(_revokes, bl);
DECODE_FINISH(bl);
- _calc_issued();
+ calc_issued();
}
void Capability::dump(Formatter *f) const
static void generate_test_instances(list<revoke_info*>& ls);
};
+ const static unsigned STATE_NOTABLE = (1<<0);
const static unsigned STATE_NEW = (1<<1);
const static unsigned STATE_IMPORTING = (1<<2);
const static unsigned STATE_CLIENTWRITEABLE = (1<<4);
_revokes.emplace_back(_pending, last_sent, last_issue);
_pending = c;
_issued |= c;
+ if (!is_notable())
+ mark_notable();
} else if (~_pending & c) {
// adding bits only. remove obsolete revocations?
_pending |= c;
inc_last_seq();
return last_sent;
}
- void _calc_issued() {
- _issued = _pending;
- for (const auto &r : _revokes) {
- _issued |= r.before;
- }
- }
void confirm_receipt(ceph_seq_t seq, unsigned caps) {
+ bool was_revoking = (_issued & ~_pending);
if (seq == last_sent) {
_revokes.clear();
_issued = caps;
if (!_revokes.empty()) {
if (_revokes.front().seq == seq)
_revokes.begin()->before = caps;
- _calc_issued();
+ calc_issued();
} else {
// seq < last_sent
_issued = caps | _pending;
}
}
- if (_issued == _pending) {
+ if (was_revoking && _issued == _pending) {
item_revoking_caps.remove_myself();
item_client_revoking_caps.remove_myself();
+ maybe_clear_notable();
}
//check_rdcaps_list();
}
changed = true;
}
if (changed) {
- _calc_issued();
- if (_issued == _pending) {
+ bool was_revoking = (_issued & ~_pending);
+ calc_issued();
+ if (was_revoking && _issued == _pending) {
item_revoking_caps.remove_myself();
item_client_revoking_caps.remove_myself();
+ maybe_clear_notable();
}
}
}
void inc_suppress() { suppress++; }
void dec_suppress() { suppress--; }
+ static bool is_wanted_notable(int wanted) {
+ return wanted & (CEPH_CAP_ANY_WR|CEPH_CAP_FILE_WR|CEPH_CAP_FILE_RD);
+ }
+ bool is_notable() const { return state & STATE_NOTABLE; }
+
bool is_stale() const;
bool is_new() const { return state & STATE_NEW; }
void mark_new() { state |= STATE_NEW; }
void mark_clientwriteable() {
if (!is_clientwriteable()) {
state |= STATE_CLIENTWRITEABLE;
+ if (!is_notable())
+ mark_notable();
}
}
void clear_clientwriteable() {
if (is_clientwriteable()) {
state &= ~STATE_CLIENTWRITEABLE;
+ maybe_clear_notable();
}
}
client_t get_client() const;
// caps this client wants to hold
- int wanted() { return _wanted; }
- void set_wanted(int w) {
- _wanted = w;
- //check_rdcaps_list();
- }
+ int wanted() const { return _wanted; }
+ void set_wanted(int w);
void inc_last_seq() { last_sent++; }
ceph_seq_t get_last_seq() { return last_sent; }
client_follows = other.client_follows;
// wanted
- _wanted = _wanted | other.wanted;
+ set_wanted(wanted() | other.wanted);
if (auth_cap)
mseq = other.mseq;
}
}
// wanted
- _wanted = _wanted | otherwanted;
+ set_wanted(wanted() | otherwanted);
}
void revoke() {
int suppress;
unsigned state;
+
+ void calc_issued() {
+ _issued = _pending;
+ for (const auto &r : _revokes) {
+ _issued |= r.before;
+ }
+ }
+
+ void mark_notable();
+ void maybe_clear_notable();
};
WRITE_CLASS_ENCODER(Capability::Export)