mds: track created inos with completed request ids in session info

Along with each session completed request (tid), also track the created
ino (if any).  This will be used to pass back to the client when they
replay requests in the next patch.

Do not bother making this a backward compatible encoding.  The only
benefit is to allow ceph-mds code to run and then old mds code to run
after it.  Given all of the other incompat changes we *just* made, this
is highly unlikely and not worth the code clutter.  If we had spanned
more releases or a stable release the story would be different.

While we are here, inline the second add_completed_request() method variant
since there is only a single caller and having it overloaded somewhat
obscures what is going on.  This also avoids a duplicate lookup in the
session map in the have_session() check and then in the (old) helper.

Signed-off-by: Sage Weil <sage@inktank.com>
This commit is contained in:
Sage Weil 2013-03-07 16:33:12 -08:00
parent 977a1cb257
commit 0bcf2ac081
5 changed files with 51 additions and 31 deletions

View File

@ -871,7 +871,7 @@ void Server::reply_request(MDRequest *mdr, MClientReply *reply, CInode *tracei,
// 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);
@ -1096,7 +1096,8 @@ void Server::handle_client_request(MClientRequest *req)
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());
@ -1209,7 +1210,7 @@ void Server::dispatch_client_request(MDRequest *mdr)
// 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);
@ -2521,7 +2522,7 @@ void Server::handle_client_open(MDRequest *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);

View File

@ -168,17 +168,22 @@ private:
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;
}
@ -349,14 +354,7 @@ public:
}
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);

View File

@ -1303,13 +1303,21 @@ void EMetaBlob::replay(MDS *mds, LogSegment *logseg, MDSlaveUpdate *slaveup)
// 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);

View File

@ -519,7 +519,7 @@ void old_rstat_t::generate_test_instances(list<old_rstat_t*>& ls)
*/
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.
@ -529,9 +529,18 @@ void session_info_t::encode(bufferlist& bl) const
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);
@ -544,10 +553,14 @@ void session_info_t::dump(Formatter *f) const
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");
@ -578,8 +591,8 @@ void session_info_t::generate_test_instances(list<session_info_t*>& ls)
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

View File

@ -484,7 +484,7 @@ inline ostream& operator<<(ostream& out, const old_rstat_t& o) {
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