// note successful request in session map?
if (req->may_write() && mdr->session && reply->get_result() == 0)
- mdr->session->add_completed_request(mdr->reqid.tid);
+ mdr->session->add_completed_request(mdr->reqid.tid, mdr->alloc_ino);
// give any preallocated inos to the session
apply_allocated_inos(mdr);
req->get_op() != CEPH_MDS_OP_OPEN &&
req->get_op() != CEPH_MDS_OP_CREATE)) {
assert(session);
- if (session->have_completed_request(req->get_reqid().tid)) {
+ inodeno_t created;
+ if (session->have_completed_request(req->get_reqid().tid, &created)) {
dout(5) << "already completed " << req->get_reqid() << dendl;
mds->messenger->send_message(new MClientReply(req, 0), req->get_connection());
// funky.
case CEPH_MDS_OP_CREATE:
if (req->get_retry_attempt() &&
- mdr->session->have_completed_request(req->get_reqid().tid))
+ mdr->session->have_completed_request(req->get_reqid().tid, NULL))
handle_client_open(mdr); // already created.. just open
else
handle_client_openc(mdr);
// O_TRUNC
if ((flags & O_TRUNC) &&
!(req->get_retry_attempt() &&
- mdr->session->have_completed_request(req->get_reqid().tid))) {
+ mdr->session->have_completed_request(req->get_reqid().tid, NULL))) {
assert(cur->is_auth());
wrlocks.insert(&cur->filelock);
public:
- void add_completed_request(tid_t t) {
- info.completed_requests.insert(t);
+ void add_completed_request(tid_t t, inodeno_t created) {
+ info.completed_requests[t] = created;
}
void trim_completed_requests(tid_t mintid) {
// trim
while (!info.completed_requests.empty() &&
- (mintid == 0 || *info.completed_requests.begin() < mintid))
+ (mintid == 0 || info.completed_requests.begin()->first < mintid))
info.completed_requests.erase(info.completed_requests.begin());
}
- bool have_completed_request(tid_t tid) const {
- return info.completed_requests.count(tid);
+ bool have_completed_request(tid_t tid, inodeno_t *pcreated) const {
+ map<tid_t,inodeno_t>::const_iterator p = info.completed_requests.find(tid);
+ if (p == info.completed_requests.end())
+ return false;
+ if (pcreated)
+ *pcreated = p->second;
+ return true;
}
}
bool have_completed_request(metareqid_t rid) {
Session *session = get_session(rid.name);
- return session && session->have_completed_request(rid.tid);
- }
- void add_completed_request(metareqid_t rid, tid_t tid=0) {
- Session *session = get_session(rid.name);
- assert(session);
- session->add_completed_request(rid.tid);
- if (tid)
- session->trim_completed_requests(tid);
+ return session && session->have_completed_request(rid.tid, NULL);
}
void trim_completed_requests(entity_name_t c, tid_t tid) {
Session *session = get_session(c);
// client requests
for (list<pair<metareqid_t, uint64_t> >::iterator p = client_reqs.begin();
p != client_reqs.end();
- ++p)
+ ++p) {
if (p->first.name.is_client()) {
- dout(10) << "EMetaBlob.replay request " << p->first << " " << p->second << dendl;
- if (mds->sessionmap.have_session(p->first.name))
- mds->sessionmap.add_completed_request(p->first, p->second);
- }
+ dout(10) << "EMetaBlob.replay request " << p->first << " trim_to " << p->second << dendl;
+
+ // if we allocated an inode, there should be exactly one client request id.
+ assert(allocated_ino == inodeno_t() || client_reqs.size() == 1);
+ Session *session = mds->sessionmap.get_session(p->first.name);
+ if (session) {
+ session->add_completed_request(p->first.tid, allocated_ino);
+ if (p->second)
+ session->trim_completed_requests(p->second);
+ }
+ }
+ }
// update segment
update_segment(logseg);
*/
void session_info_t::encode(bufferlist& bl) const
{
- ENCODE_START(2, 2, bl);
+ ENCODE_START(3, 3, bl);
::encode(inst, bl);
::encode(completed_requests, bl);
::encode(prealloc_inos, bl); // hacky, see below.
void session_info_t::decode(bufferlist::iterator& p)
{
- DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, p);
+ DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, p);
::decode(inst, p);
- ::decode(completed_requests, p);
+ if (struct_v == 2) {
+ set<tid_t> s;
+ ::decode(completed_requests, p);
+ while (!s.empty()) {
+ completed_requests[*s.begin()] = inodeno_t();
+ s.erase(s.begin());
+ }
+ } else {
+ ::decode(completed_requests, p);
+ }
::decode(prealloc_inos, p);
::decode(used_inos, p);
prealloc_inos.insert(used_inos);
f->dump_stream("inst") << inst;
f->open_array_section("completed_requests");
- for (set<tid_t>::const_iterator p = completed_requests.begin();
+ for (map<tid_t,inodeno_t>::const_iterator p = completed_requests.begin();
p != completed_requests.end();
- ++p)
- f->dump_unsigned("tid", *p);
+ ++p) {
+ f->open_object_section("request");
+ f->dump_unsigned("tid", p->first);
+ f->dump_stream("created_ino") << p->second;
+ f->close_section();
+ }
f->close_section();
f->open_array_section("prealloc_inos");
ls.push_back(new session_info_t);
ls.push_back(new session_info_t);
ls.back()->inst = entity_inst_t(entity_name_t::MDS(12), entity_addr_t());
- ls.back()->completed_requests.insert(234);
- ls.back()->completed_requests.insert(237);
+ ls.back()->completed_requests.insert(make_pair(234, inodeno_t(111222)));
+ ls.back()->completed_requests.insert(make_pair(237, inodeno_t(222333)));
ls.back()->prealloc_inos.insert(333, 12);
ls.back()->prealloc_inos.insert(377, 112);
// we can't add used inos; they're cleared on decode
struct session_info_t {
entity_inst_t inst;
- set<tid_t> completed_requests;
+ map<tid_t,inodeno_t> completed_requests;
interval_set<inodeno_t> prealloc_inos; // preallocated, ready to use.
interval_set<inodeno_t> used_inos; // journaling use