capseq_t last_sent, last_recv;
bool suppress;
+ bool stale;
public:
xlist<Capability*>::item session_caps_item;
wanted_caps(want),
last_sent(s),
last_recv(s),
- suppress(false),
+ suppress(false), stale(false),
session_caps_item(this) {
}
Capability(CInode *i, Export& other) :
inode(i),
wanted_caps(other.wanted),
last_sent(0), last_recv(0),
+ suppress(false), stale(false),
session_caps_item(this) {
// issued vs pending
if (other.issued & ~other.pending)
bool is_suppress() { return suppress; }
void set_suppress(bool b) { suppress = b; }
+ bool is_stale() { return stale; }
+ void set_stale(bool b) { stale = b; }
+
CInode *get_inode() { return inode; }
void set_inode(CInode *i) { inode = i; }
void add_to_cap_list(xlist<Capability*>& ls) {
// issue caps; return seq number.
capseq_t issue(int c) {
- //int was = pending();
- //no! if (c == was && last_sent) return -1; // repeat of previous?
-
++last_sent;
cap_history[last_sent] = c;
-
- /* no!
- // not recalling, just adding?
- if (c & ~was &&
- cap_history.count(last_sent-1)) {
- cap_history.erase(last_sent-1);
- }
- */
return last_sent;
}
capseq_t get_last_seq() { return last_sent; }
return r;
}
+ void revoke() {
+ if (pending())
+ issue(0);
+ confirm_receipt(last_sent, 0);
+ }
+
// serializers
void _encode(bufferlist& bl) {
bl.append((char*)&wanted_caps, sizeof(wanted_caps));
return (nissued == 0); // true if no re-issued, no callbacks
}
+void Locker::revoke_stale_caps(Session *session)
+{
+ dout(10) << "revoke_stale_caps for client " << session->inst.name << dendl;
+
+ for (xlist<Capability*>::iterator p = session->caps.begin(); !p.end(); ++p) {
+ Capability *cap = *p;
+ CInode *in = cap->get_inode();
+ int issued = cap->issued();
+ if (issued) {
+ dout(10) << " revoking " << cap_string(issued) << " on " << *in << dendl;
+ cap->revoke();
+ file_eval(&in->filelock);
+ } else {
+ dout(10) << " nothing issued on " << *in << dendl;
+ }
+ cap->set_stale(true);
+ }
+}
class C_MDL_RequestInodeFileCaps : public Context {
Locker *locker;
using std::set;
class MDS;
+class Session;
class CDir;
class CInode;
class CDentry;
version_t issue_file_data_version(CInode *in);
Capability* issue_new_caps(CInode *in, int mode, Session *session);
bool issue_caps(CInode *in);
+ void revoke_stale_caps(Session *session);
protected:
void handle_client_file_caps(class MClientFileCaps *m);
void Server::find_idle_sessions()
{
- dout(10) << "find_idle_sessions " << mds->sessionmap.session_list.size() << dendl;
+ dout(10) << "find_idle_sessions" << dendl;
utime_t cutoff = g_clock.now();
cutoff -= g_conf.mds_cap_timeout;
while (1) {
- Session *oldest = mds->sessionmap.get_oldest_session();
- if (!oldest) break;
- dout(20) << "oldest session is " << oldest->inst << dendl;
- if (oldest->last_cap_renew >= cutoff) {
- dout(20) << "oldest session is " << oldest->inst << " and sufficiently new ("
- << oldest->last_cap_renew << ")" << dendl;
+ Session *session = mds->sessionmap.get_oldest_active_session();
+ if (!session) break;
+ dout(20) << "laggiest session is " << session->inst << dendl;
+ if (session->last_cap_renew >= cutoff) {
+ dout(20) << "laggiest session is " << session->inst << " and sufficiently new ("
+ << session->last_cap_renew << ")" << dendl;
break;
}
- dout(10) << " expiring caps for " << oldest << " " << oldest->inst << " last " << oldest->last_cap_renew << dendl;
- // write me!!!
- break;
+ dout(10) << "new stale session " << session->inst << " last " << session->last_cap_renew << dendl;
+ mds->sessionmap.mark_session_stale(session);
+ mds->locker->revoke_stale_caps(session);
}
}
bool is_opening() { return state == STATE_OPENING; }
bool is_open() { return state == STATE_OPEN; }
bool is_closing() { return state == STATE_CLOSING; }
+ bool is_stale() { return state == STATE_STALE; }
// -- caps --
private:
MDS *mds;
hash_map<entity_name_t, Session*> session_map;
public:
- xlist<Session*> session_list;
+ xlist<Session*> active_sessions;
+ xlist<Session*> stale_sessions;
public: // i am lazy
version_t version, projected, committing, committed;
return session_map[i.name];
Session *s = session_map[i.name] = new Session;
s->inst = i;
- session_list.push_back(&s->session_list_item);
- assert(session_list.back() == s);
return s;
}
void remove_session(Session *s) {
}
void touch_session(Session *s) {
s->last_cap_renew = g_clock.now();
- session_list.push_back(&s->session_list_item);
+ active_sessions.push_back(&s->session_list_item);
}
- Session *get_oldest_session() {
- if (session_list.empty()) return 0;
- return session_list.front();
+ Session *get_oldest_active_session() {
+ if (active_sessions.empty()) return 0;
+ return active_sessions.front();
+ }
+ void mark_session_stale(Session *s) {
+ stale_sessions.push_back(&s->session_list_item);
}
void get_client_set(set<int>& s) {