case CEPH_SESSION_RENEWCAPS:
mds_sessions[from].cap_ttl =
mds_sessions[from].last_cap_renew_request + mdsmap->get_session_timeout();
+ wake_inode_waiters(from);
break;
case CEPH_SESSION_STALE:
- // FIXME
+ mds_sessions[from].was_stale = true;
break;
-
default:
assert(0);
}
dout(10) << " path " << path << dendl;
in->caps[mds]->seq = 0; // reset seq.
- m->add_cap(p->first.ino, in->caps[mds]->cap_id,
- path.get_ino(), path.get_path(),
+ m->add_cap(p->first.ino, path.get_ino(), path.get_path(), // ino
in->caps_wanted(), // wanted
in->caps[mds]->issued, // issued
in->inode.size, in->inode.mtime, in->inode.atime, in->snaprealm->ino);
ls.clear();
}
+void Client::wake_inode_waiters(int mds_num)
+{
+ MDSSession * mds = &mds_sessions[mds_num];
+ xlist<InodeCap*>::iterator iter = mds->caps.begin();
+ while (!iter.end()){
+ signal_cond_list((*iter)->inode->waitfor_caps);
+ ++iter;
+ }
+}
// flush dirty data (from objectcache)
in->exporting_mseq = 0;
}
in->caps[mds] = cap = new InodeCap;
+ mds_sessions[mds].caps.push_back(&cap->cap_item);
+ cap->session = &mds_sessions[mds];
+ cap->inode = in;
+ cap->gen = mds_sessions[mds].cap_gen;
cap_list.push_back(&in->cap_item);
}
i.seq = cap->seq;
i.migrate_seq = cap->mseq;
session->release->caps.push_back(i);
+
+ cap->cap_item.remove_myself();
if (in->auth_cap == cap)
in->auth_cap = NULL;
void Client::renew_caps()
{
- dout(10) << "renew_caps" << dendl;
+ dout(10) << "renew_caps()" << dendl;
last_cap_renew = g_clock.now();
for (map<int,MDSSession>::iterator p = mds_sessions.begin();
p != mds_sessions.end();
p++) {
dout(15) << "renew_caps requesting from mds" << p->first << dendl;
- p->second.last_cap_renew_request = g_clock.now();
- messenger->send_message(new MClientSession(CEPH_SESSION_REQUEST_RENEWCAPS),
- mdsmap->get_inst(p->first));
+ renew_caps(p->first);
}
}
+void Client::renew_caps(const int session) {
+ dout(10) << "renew_caps(session number)" << dendl;
+ mds_sessions[session].last_cap_renew_request = g_clock.now();
+ messenger->send_message(new MClientSession(CEPH_SESSION_REQUEST_RENEWCAPS),
+ mdsmap->get_inst(session));
+
+}
+
// ===============================================================
// high level (POSIXy) interface
- when Dir is empty, it's removed (and it's Inode ref--)
*/
+struct InodeCap;
+struct MDSSession {
+ version_t seq;
+ __u64 cap_gen;
+ utime_t cap_ttl, last_cap_renew_request;
+ int num_caps;
+ entity_inst_t inst;
+ bool closing;
+ bool was_stale;
+
+ xlist<InodeCap*> caps;
+
+ MClientCapRelease *release;
+
+ MDSSession() : seq(0), cap_gen(0), num_caps(0),
+ closing(false), was_stale(false), release(NULL) {}
+};
class Dir;
class Inode;
bool is_empty() { return dentries.empty(); }
};
-
-struct InodeCap;
-
struct SnapRealm {
inodeno_t ino;
int nref;
}
struct InodeCap {
+ MDSSession *session;
+ Inode *inode;
+ xlist<InodeCap*>::item cap_item;
+
__u64 cap_id;
unsigned issued;
unsigned implemented;
unsigned wanted; // as known to mds.
__u64 seq;
__u32 mseq; // migration seq
+ __u32 gen;
- InodeCap() : issued(0), implemented(0), wanted(0), seq(0), mseq(0) {}
+ InodeCap() : session(NULL), inode(NULL), cap_item(this), issued(0),
+ implemented(0), wanted(0), seq(0), mseq(0), gen(0) {}
};
struct CapSnap {
return caps.size() || exporting_mds >= 0;
}
+ bool cap_is_valid(InodeCap* cap) {
+ cout << "cap_gen " << cap->session-> cap_gen << std::endl
+ << "session gen " << cap->gen << std::endl
+ << "cap expire " << cap->session->cap_ttl << std::endl
+ << "cur time " << g_clock.now() << std::endl;
+ if ((cap->session->cap_gen <= cap->gen)
+ && (g_clock.now() < cap->session->cap_ttl)) {
+ return true;
+ }
+ //if we make it here, the capabilities aren't up-to-date
+ cap->session->was_stale = true;
+ return true;
+ }
+
int caps_issued() {
int c = exporting_issued | snap_caps;
for (map<int,InodeCap*>::iterator it = caps.begin();
it != caps.end();
it++)
- c |= it->second->issued;
+ if (cap_is_valid(it->second))
+ c |= it->second->issued;
return c;
}
Context *tick_event;
utime_t last_cap_renew;
void renew_caps();
+ void renew_caps(int s);
public:
void tick();
bufferlist signed_ticket;
// mds sessions
- struct MDSSession {
- version_t seq;
- __u64 cap_gen;
- utime_t cap_ttl, last_cap_renew_request;
- int num_caps;
- entity_inst_t inst;
- bool closing;
-
- MClientCapRelease *release;
-
- MDSSession() : seq(0), cap_gen(0), num_caps(0), closing(false), release(NULL) {}
- };
map<int, MDSSession> mds_sessions; // mds -> push seq
map<int, list<Cond*> > waiting_for_session;
list<Cond*> waiting_for_mdsmap;
Mutex client_lock;
// helpers
+ void wake_inode_waiters(int mds);
void wait_on_list(list<Cond*>& ls);
void signal_cond_list(list<Cond*>& ls);