for (auto q = p->second.second.begin(); q != p->second.second.end(); ++q)
client_exports[q->first].insert(target);
}
- for (map<client_t, set<mds_rank_t> >::iterator p = client_exports.begin();
- p != client_exports.end();
- ++p) {
- entity_inst_t inst = mds->sessionmap.get_inst(entity_name_t::CLIENT(p->first.v));
- for (set<mds_rank_t>::iterator q = p->second.begin(); q != p->second.end(); ++q)
- rejoins[*q]->client_map[p->first] = inst;
+ for (auto& p : client_exports) {
+ Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(p.first.v));
+ for (auto& q : p.second) {
+ auto rejoin = rejoins[q];
+ rejoin->client_map[p.first] = session->info.inst;
+ rejoin->client_metadata_map[p.first] = session->info.client_metadata;
+ }
}
}
// check cap exports.
rejoin_client_map.insert(weak->client_map.begin(), weak->client_map.end());
+ rejoin_client_metadata_map.insert(weak->client_metadata_map.begin(),
+ weak->client_metadata_map.end());
for (auto p = weak->cap_exports.begin(); p != weak->cap_exports.end(); ++p) {
CInode *in = get_inode(p->first);
rejoin_session_map.empty()) {
C_MDC_RejoinSessionsOpened *finish = new C_MDC_RejoinSessionsOpened(this);
version_t pv = mds->server->prepare_force_open_sessions(rejoin_client_map,
+ rejoin_client_metadata_map,
finish->session_map);
- mds->mdlog->start_submit_entry(new ESessions(pv, rejoin_client_map), finish);
+ ESessions *le = new ESessions(pv, std::move(rejoin_client_map),
+ std::move(rejoin_client_metadata_map));
+ mds->mdlog->start_submit_entry(le, finish);
mds->mdlog->flush();
rejoin_client_map.clear();
+ rejoin_client_metadata_map.clear();
return true;
}
set<mds_rank_t> rejoin_ack_gather; // nodes from whom i need a rejoin ack
map<mds_rank_t,map<inodeno_t,map<client_t,Capability::Import> > > rejoin_imported_caps;
map<inodeno_t,pair<mds_rank_t,map<client_t,Capability::Export> > > rejoin_slave_exports;
+
map<client_t,entity_inst_t> rejoin_client_map;
+ map<client_t,client_metadata_t> rejoin_client_metadata_map;
map<client_t,pair<Session*,uint64_t> > rejoin_session_map;
map<inodeno_t,pair<mds_rank_t,map<client_t,cap_reconnect_t> > > cap_exports; // ino -> target, client -> capex
// Dump sessions, decorated with recovery/replay status
f->open_array_section("sessions");
const ceph::unordered_map<entity_name_t, Session*> session_map = sessionmap.get_sessions();
- for (ceph::unordered_map<entity_name_t,Session*>::const_iterator p = session_map.begin();
- p != session_map.end();
- ++p) {
- if (!p->first.is_client()) {
+ for (auto& p : session_map) {
+ if (!p.first.is_client()) {
continue;
}
- Session *s = p->second;
+ Session *s = p.second;
if (!filter.match(*s, std::bind(&Server::waiting_for_reconnect, server, std::placeholders::_1))) {
continue;
}
f->open_object_section("session");
- f->dump_int("id", p->first.num());
+ f->dump_int("id", p.first.num());
f->dump_int("num_leases", s->leases.size());
f->dump_int("num_caps", s->caps.size());
f->dump_string("state", s->get_state_name());
f->dump_int("replay_requests", is_clientreplay() ? s->get_request_count() : 0);
f->dump_unsigned("completed_requests", s->get_num_completed_requests());
- f->dump_bool("reconnecting", server->waiting_for_reconnect(p->first.num()));
+ f->dump_bool("reconnecting", server->waiting_for_reconnect(p.first.num()));
f->dump_stream("inst") << s->info.inst;
f->open_object_section("client_metadata");
- for (map<string, string>::const_iterator i = s->info.client_metadata.begin();
- i != s->info.client_metadata.end(); ++i) {
- f->dump_string(i->first.c_str(), i->second);
+ for (auto& q : s->info.client_metadata) {
+ f->dump_string(q.first.c_str(), q.second);
}
f->close_section(); // client_metadata
f->close_section(); //session
// fill export message with cache data
MExportDir *req = new MExportDir(dir->dirfrag(), it->second.tid);
map<client_t,entity_inst_t> exported_client_map;
+ map<client_t,client_metadata_t> exported_client_metadata_map;
uint64_t num_exported_inodes = encode_export_dir(req->export_data,
dir, // recur start point
- exported_client_map);
- encode(exported_client_map, req->client_map,
- mds->mdsmap->get_up_features());
+ exported_client_map,
+ exported_client_metadata_map);
+ encode(exported_client_map, req->client_map, mds->mdsmap->get_up_features());
+ encode(exported_client_metadata_map, req->client_map);
// add bounds to message
set<CDir*> bounds;
* is pretty arbitrary and dumb.
*/
void Migrator::encode_export_inode(CInode *in, bufferlist& enc_state,
- map<client_t,entity_inst_t>& exported_client_map)
+ map<client_t,entity_inst_t>& exported_client_map,
+ map<client_t,client_metadata_t>& exported_client_metadata_map)
{
dout(7) << "encode_export_inode " << *in << dendl;
assert(!in->is_replica(mds->get_nodeid()));
in->encode_export(enc_state);
// caps
- encode_export_inode_caps(in, true, enc_state, exported_client_map);
+ encode_export_inode_caps(in, true, enc_state, exported_client_map, exported_client_metadata_map);
}
void Migrator::encode_export_inode_caps(CInode *in, bool auth_cap, bufferlist& bl,
- map<client_t,entity_inst_t>& exported_client_map)
+ map<client_t,entity_inst_t>& exported_client_map,
+ map<client_t,client_metadata_t>& exported_client_metadata_map)
{
dout(20) << "encode_export_inode_caps " << *in << dendl;
// make note of clients named by exported capabilities
for (const auto &p : in->get_client_caps()) {
- exported_client_map[p.first] = mds->sessionmap.get_inst(entity_name_t::CLIENT(p.first.v));
+ if (exported_client_map.count(p.first))
+ continue;
+ Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(p.first.v));
+ exported_client_map[p.first] = session->info.inst;
+ exported_client_metadata_map[p.first] = session->info.client_metadata;
}
}
uint64_t Migrator::encode_export_dir(bufferlist& exportbl,
CDir *dir,
- map<client_t,entity_inst_t>& exported_client_map)
+ map<client_t,entity_inst_t>& exported_client_map,
+ map<client_t,client_metadata_t>& exported_client_metadata_map)
{
uint64_t num_exported = 0;
// -- inode
exportbl.append("I", 1); // inode dentry
- encode_export_inode(in, exportbl, exported_client_map); // encode, and (update state for) export
+ encode_export_inode(in, exportbl, exported_client_map, exported_client_metadata_map); // encode, and (update state for) export
// directory?
list<CDir*> dfs;
// subdirs
for (auto &dir : subdirs)
- num_exported += encode_export_dir(exportbl, dir, exported_client_map);
+ num_exported += encode_export_dir(exportbl, dir, exported_client_map, exported_client_metadata_map);
return num_exported;
}
// include imported sessions in EImportStart
auto cmp = m->client_map.cbegin();
map<client_t,entity_inst_t> client_map;
+ map<client_t,client_metadata_t> client_metadata_map;
decode(client_map, cmp);
+ decode(client_metadata_map, cmp);
assert(cmp.end());
- le->cmapv = mds->server->prepare_force_open_sessions(client_map, onlogged->imported_session_map);
+ le->cmapv = mds->server->prepare_force_open_sessions(client_map, client_metadata_map,
+ onlogged->imported_session_map);
encode(client_map, le->client_map, mds->mdsmap->get_up_features());
+ encode(client_metadata_map, le->client_map);
auto blp = m->export_data.cbegin();
int num_imported_inodes = 0;
MExportCaps *ex = new MExportCaps;
ex->ino = in->ino();
- encode_export_inode_caps(in, false, ex->cap_bl, ex->client_map);
+ encode_export_inode_caps(in, false, ex->cap_bl, ex->client_map, ex->client_metadata_map);
mds->send_message_mds(ex, dest);
}
in->auth_pin(this);
map<client_t,entity_inst_t> client_map;
+ map<client_t,client_metadata_t> client_metadata_map;
client_map.swap(ex->client_map);
+ client_metadata_map.swap(ex->client_metadata_map);
C_M_LoggedImportCaps *finish = new C_M_LoggedImportCaps(
this, in, mds_rank_t(ex->get_source().num()));
- version_t pv = mds->server->prepare_force_open_sessions(client_map,
+ version_t pv = mds->server->prepare_force_open_sessions(client_map, client_metadata_map,
finish->imported_session_map);
// decode new caps
auto blp = ex->cap_bl.cbegin();
assert(!finish->peer_exports.empty()); // thus, inode is pinned.
// journal open client sessions
-
- ESessions *le = new ESessions(pv, client_map);
+ ESessions *le = new ESessions(pv, std::move(client_map),
+ std::move(client_metadata_map));
mds->mdlog->start_submit_entry(le, finish);
mds->mdlog->flush();
void get_export_client_set(CInode *in, set<client_t> &client_set);
void encode_export_inode(CInode *in, bufferlist& bl,
- map<client_t,entity_inst_t>& exported_client_map);
+ map<client_t,entity_inst_t>& exported_client_map,
+ map<client_t,client_metadata_t>& exported_client_metadata_map);
void encode_export_inode_caps(CInode *in, bool auth_cap, bufferlist& bl,
- map<client_t,entity_inst_t>& exported_client_map);
+ map<client_t,entity_inst_t>& exported_client_map,
+ map<client_t,client_metadata_t>& exported_client_metadata_map);
void finish_export_inode(CInode *in, mds_rank_t target,
map<client_t,Capability::Import>& peer_imported,
list<MDSInternalContextBase*>& finished);
uint64_t encode_export_dir(bufferlist& exportbl,
CDir *dir,
- map<client_t,entity_inst_t>& exported_client_map);
+ map<client_t,entity_inst_t>& exported_client_map,
+ map<client_t,client_metadata_t>& exported_client_metadata_map);
void finish_export_dir(CDir *dir, mds_rank_t target,
map<inodeno_t,map<client_t,Capability::Import> >& peer_imported,
list<MDSInternalContextBase*>& finished, int *num_dentries);
session->is_killing() ||
terminating_sessions) {
dout(10) << "currently open|opening|stale|killing, dropping this req" << dendl;
- // set client metadata for session opened by prepare_force_open_sessions
- if (!m->client_meta.empty())
- session->set_client_metadata(m->client_meta);
m->put();
return;
}
return;
}
- session->set_client_metadata(m->client_meta);
- dout(20) << __func__ << " CEPH_SESSION_REQUEST_OPEN "
- << session->info.client_metadata.size() << " metadata entries:" << dendl;
- for (map<string, string>::iterator i = session->info.client_metadata.begin();
- i != session->info.client_metadata.end(); ++i) {
- dout(20) << " " << i->first << ": " << i->second << dendl;
- }
-
- // Special case for the 'root' metadata path; validate that the claimed
- // root is actually within the caps of the session
- if (session->info.client_metadata.count("root")) {
- const auto claimed_root = session->info.client_metadata.at("root");
- // claimed_root has a leading "/" which we strip before passing
- // into caps check
- if (claimed_root.empty() || claimed_root[0] != '/' ||
- !session->auth_caps.path_capable(claimed_root.substr(1))) {
- derr << __func__ << " forbidden path claimed as mount root: "
- << claimed_root << " by " << m->get_source() << dendl;
- // Tell the client we're rejecting their open
- mds->send_message_client(new MClientSession(CEPH_SESSION_REJECT), session);
- mds->clog->warn() << "client session with invalid root '" <<
- claimed_root << "' denied (" << session->info.inst << ")";
- session->clear();
- // Drop out; don't record this session in SessionMap or journal it.
- break;
+ {
+ client_metadata_t client_metadata(std::move(m->client_meta));
+ dout(20) << __func__ << " CEPH_SESSION_REQUEST_OPEN metadata entries:" << dendl;
+ for (auto& p : client_metadata) {
+ dout(20) << " " << p.first << ": " << p.second << dendl;
+ }
+
+ client_metadata_t::iterator it;
+ // Special case for the 'root' metadata path; validate that the claimed
+ // root is actually within the caps of the session
+ it = client_metadata.find("root");
+ if (it != client_metadata.end()) {
+ auto claimed_root = it->second;
+ // claimed_root has a leading "/" which we strip before passing
+ // into caps check
+ if (claimed_root.empty() || claimed_root[0] != '/' ||
+ !session->auth_caps.path_capable(claimed_root.substr(1))) {
+ derr << __func__ << " forbidden path claimed as mount root: "
+ << claimed_root << " by " << m->get_source() << dendl;
+ // Tell the client we're rejecting their open
+ mds->send_message_client(new MClientSession(CEPH_SESSION_REJECT), session);
+ mds->clog->warn() << "client session with invalid root '" << claimed_root
+ << "' denied (" << session->info.inst << ")";
+ session->clear();
+ // Drop out; don't record this session in SessionMap or journal it.
+ break;
+ }
}
- }
- if (session->is_closed())
- mds->sessionmap.add_session(session);
+ session->set_client_metadata(client_metadata);
- pv = mds->sessionmap.mark_projected(session);
- sseq = mds->sessionmap.set_state(session, Session::STATE_OPENING);
- mds->sessionmap.touch_session(session);
- mdlog->start_submit_entry(new ESession(m->get_source_inst(), true, pv, m->client_meta),
- new C_MDS_session_finish(this, session, sseq, true, pv));
- mdlog->flush();
+ if (session->is_closed())
+ mds->sessionmap.add_session(session);
+
+ pv = mds->sessionmap.mark_projected(session);
+ sseq = mds->sessionmap.set_state(session, Session::STATE_OPENING);
+ mds->sessionmap.touch_session(session);
+ mdlog->start_submit_entry(new ESession(m->get_source_inst(), true, pv,
+ std::move(client_metadata)),
+ new C_MDS_session_finish(this, session, sseq, true, pv));
+ mdlog->flush();
+ }
break;
case CEPH_SESSION_REQUEST_RENEWCAPS:
* - sessions learned from other MDSs during a cross-MDS rename
*/
version_t Server::prepare_force_open_sessions(map<client_t,entity_inst_t>& cm,
+ map<client_t,client_metadata_t>& cmm,
map<client_t, pair<Session*,uint64_t> >& smap)
{
version_t pv = mds->sessionmap.get_projected();
<< dendl;
mds->objecter->with_osdmap(
- [this, &cm](const OSDMap &osd_map) {
+ [this, &cm, &cmm](const OSDMap &osd_map) {
for (auto p = cm.begin(); p != cm.end(); ) {
if (osd_map.is_blacklisted(p->second.addr)) {
dout(10) << " ignoring blacklisted client." << p->first
<< " (" << p->second.addr << ")" << dendl;
+ cmm.erase(p->first);
cm.erase(p++);
} else {
++p;
session->is_closing() ||
session->is_killing()) {
sseq = mds->sessionmap.set_state(session, Session::STATE_OPENING);
+ auto q = cmm.find(p->first);
+ if (q != cmm.end())
+ session->info.client_metadata.merge(q->second);
} else {
assert(session->is_open() ||
session->is_opening() ||
// imported caps
map<client_t,entity_inst_t> client_map;
+ map<client_t, client_metadata_t> client_metadata_map;
decode(client_map, blp);
- prepare_force_open_sessions(client_map, mdr->more()->imported_session_map);
+ decode(client_metadata_map, blp);
+ prepare_force_open_sessions(client_map, client_metadata_map,
+ mdr->more()->imported_session_map);
encode(client_map, *client_map_bl, mds->mdsmap->get_up_features());
+ encode(client_metadata_map, *client_map_bl);
list<ScatterLock*> updated_scatterlocks;
mdcache->migrator->decode_import_inode(srcdn, blp, srcdn->authority().first, mdr->ls,
// export srci?
if (srcdn->is_auth() && srcdnl->is_primary()) {
// set export bounds for CInode::encode_export()
- list<CDir*> bounds;
- if (srcdnl->get_inode()->is_dir()) {
- srcdnl->get_inode()->get_dirfrags(bounds);
- for (list<CDir*>::iterator p = bounds.begin(); p != bounds.end(); ++p)
- (*p)->state_set(CDir::STATE_EXPORTBOUND);
- }
+ if (reply) {
+ list<CDir*> bounds;
+ if (srcdnl->get_inode()->is_dir()) {
+ srcdnl->get_inode()->get_dirfrags(bounds);
+ for (list<CDir*>::iterator p = bounds.begin(); p != bounds.end(); ++p)
+ (*p)->state_set(CDir::STATE_EXPORTBOUND);
+ }
- map<client_t,entity_inst_t> exported_client_map;
- bufferlist inodebl;
- mdcache->migrator->encode_export_inode(srcdnl->get_inode(), inodebl,
- exported_client_map);
+ map<client_t,entity_inst_t> exported_client_map;
+ map<client_t, client_metadata_t> exported_client_metadata_map;
+ bufferlist inodebl;
+ mdcache->migrator->encode_export_inode(srcdnl->get_inode(), inodebl,
+ exported_client_map,
+ exported_client_metadata_map);
- for (list<CDir*>::iterator p = bounds.begin(); p != bounds.end(); ++p)
- (*p)->state_clear(CDir::STATE_EXPORTBOUND);
+ for (list<CDir*>::iterator p = bounds.begin(); p != bounds.end(); ++p)
+ (*p)->state_clear(CDir::STATE_EXPORTBOUND);
- if (reply) {
encode(exported_client_map, reply->inode_export, mds->mdsmap->get_up_features());
+ encode(exported_client_metadata_map, reply->inode_export);
reply->inode_export.claim_append(inodebl);
reply->inode_export_v = srcdnl->get_inode()->inode.version;
}
void _session_logged(Session *session, uint64_t state_seq,
bool open, version_t pv, interval_set<inodeno_t>& inos,version_t piv);
version_t prepare_force_open_sessions(map<client_t,entity_inst_t> &cm,
+ map<client_t,client_metadata_t>& cmm,
map<client_t,pair<Session*,uint64_t> >& smap);
void finish_force_open_sessions(const map<client_t,pair<Session*,uint64_t> >& smap,
bool dec_import=true);
recall_release_count = 0;
}
-void Session::set_client_metadata(map<string, string> const &meta)
+void Session::set_client_metadata(const client_metadata_t& meta)
{
info.client_metadata = meta;
for (const auto &m : metadata) {
const auto &k = m.first;
const auto &v = m.second;
- if (session.info.client_metadata.count(k) == 0) {
+ auto it = session.info.client_metadata.find(k);
+ if (it == session.info.client_metadata.end()) {
return false;
}
- if (session.info.client_metadata.at(k) != v) {
+ if (it->second != v) {
return false;
}
}
}
}
void decode(bufferlist::const_iterator &p);
- void set_client_metadata(std::map<std::string, std::string> const &meta);
+ void set_client_metadata(const client_metadata_t& meta);
const std::string& get_human_name() const {return human_name;}
// Ephemeral state for tracking progress of capability recalls
s.insert(p->second);
}
- void replay_open_sessions(map<client_t,entity_inst_t>& client_map) {
+ void replay_open_sessions(map<client_t,entity_inst_t>& client_map,
+ map<client_t,client_metadata_t>& client_metadata_map) {
for (map<client_t,entity_inst_t>::iterator p = client_map.begin();
p != client_map.end();
++p) {
Session *s = get_or_add_session(p->second);
+ auto q = client_metadata_map.find(p->first);
+ if (q != client_metadata_map.end())
+ s->info.client_metadata.merge(q->second);
+
set_state(s, Session::STATE_OPEN);
replay_dirty_session(s);
}
version_t inotablev{0};
// Client metadata stored during open
- std::map<std::string, std::string> client_metadata;
+ client_metadata_t client_metadata;
public:
ESession() : LogEvent(EVENT_SESSION), open(false) { }
ESession(const entity_inst_t& inst, bool o, version_t v,
- const std::map<std::string, std::string> &cm) :
+ client_metadata_t &&cm) :
LogEvent(EVENT_SESSION),
- client_inst(inst),
- open(o),
- cmapv(v),
- inotablev(0),
- client_metadata(cm) {
- }
+ client_inst(inst), open(o), cmapv(v), inotablev(0),
+ client_metadata(std::move(cm)) { }
ESession(const entity_inst_t& inst, bool o, version_t v,
const interval_set<inodeno_t>& i, version_t iv) :
LogEvent(EVENT_SESSION),
- client_inst(inst),
- open(o),
- cmapv(v),
- inos(i), inotablev(iv) { }
+ client_inst(inst), open(o), cmapv(v), inos(i), inotablev(iv) { }
void encode(bufferlist& bl, uint64_t features) const override;
void decode(bufferlist::const_iterator& bl) override;
class ESessions : public LogEvent {
protected:
version_t cmapv; // client map version
+ bool old_style_encode;
public:
map<client_t,entity_inst_t> client_map;
- bool old_style_encode;
+ map<client_t,client_metadata_t> client_metadata_map;
ESessions() : LogEvent(EVENT_SESSIONS), cmapv(0), old_style_encode(false) { }
- ESessions(version_t pv, map<client_t,entity_inst_t>& cm) :
+ ESessions(version_t pv, map<client_t,entity_inst_t>&& cm,
+ map<client_t,client_metadata_t>&& cmm) :
LogEvent(EVENT_SESSIONS),
- cmapv(pv),
- old_style_encode(false) {
- client_map.swap(cm);
- }
+ cmapv(pv), old_style_encode(false),
+ client_map(std::move(cm)),
+ client_metadata_map(std::move(cmm)) {}
void mark_old_encoding() { old_style_encode = true; }
void ESession::encode(bufferlist &bl, uint64_t features) const
{
- ENCODE_START(4, 3, bl);
+ ENCODE_START(5, 5, bl);
encode(stamp, bl);
encode(client_inst, bl, features);
encode(open, bl);
void ESession::decode(bufferlist::const_iterator &bl)
{
- DECODE_START_LEGACY_COMPAT_LEN(4, 3, 3, bl);
+ DECODE_START_LEGACY_COMPAT_LEN(5, 3, 3, bl);
if (struct_v >= 2)
decode(stamp, bl);
decode(client_inst, bl);
decode(cmapv, bl);
decode(inos, bl);
decode(inotablev, bl);
- if (struct_v >= 4) {
+ if (struct_v == 4) {
+ decode(client_metadata.kv_map, bl);
+ } else if (struct_v >= 5) {
decode(client_metadata, bl);
}
DECODE_FINISH(bl);
f->dump_stream("inos") << inos;
f->dump_int("inotable version", inotablev);
f->open_object_section("client_metadata");
- for (map<string, string>::const_iterator i = client_metadata.begin();
- i != client_metadata.end(); ++i) {
- f->dump_string(i->first.c_str(), i->second);
+ for (auto& p : client_metadata) {
+ f->dump_string(p.first.c_str(), p.second);
}
f->close_section(); // client_metadata
}
void ESessions::encode(bufferlist &bl, uint64_t features) const
{
- ENCODE_START(1, 1, bl);
+ ENCODE_START(2, 1, bl);
encode(client_map, bl, features);
encode(cmapv, bl);
encode(stamp, bl);
+ encode(client_metadata_map, bl);
ENCODE_FINISH(bl);
}
void ESessions::decode_new(bufferlist::const_iterator &bl)
{
- DECODE_START(1, bl);
+ DECODE_START(2, bl);
decode(client_map, bl);
decode(cmapv, bl);
- if (!bl.end())
- decode(stamp, bl);
+ decode(stamp, bl);
+ if (struct_v >= 2)
+ decode(client_metadata_map, bl);
DECODE_FINISH(bl);
}
} else {
dout(10) << "ESessions.replay sessionmap " << mds->sessionmap.get_version()
<< " < " << cmapv << dendl;
- mds->sessionmap.replay_open_sessions(client_map);
+ mds->sessionmap.replay_open_sessions(client_map, client_metadata_map);
assert(mds->sessionmap.get_version() == cmapv);
}
update_segment();
<< " < " << cmapv << dendl;
// open client sessions?
map<client_t,entity_inst_t> cm;
+ map<client_t,client_metadata_t> cmm;
auto blp = client_map.cbegin();
using ceph::decode;
decode(cm, blp);
- mds->sessionmap.replay_open_sessions(cm);
+ if (!blp.end())
+ decode(cmm, blp);
+ mds->sessionmap.replay_open_sessions(cm, cmm);
+
assert(mds->sessionmap.get_version() == cmapv);
}
}
dout(10) << "EImportStart.replay sessionmap " << mds->sessionmap.get_version()
<< " < " << cmapv << dendl;
map<client_t,entity_inst_t> cm;
+ map<client_t,client_metadata_t> cmm;
auto blp = client_map.cbegin();
using ceph::decode;
decode(cm, blp);
- mds->sessionmap.replay_open_sessions(cm);
- if (mds->sessionmap.get_version() != cmapv)
- {
+ if (!blp.end())
+ decode(cmm, blp);
+ mds->sessionmap.replay_open_sessions(cm, cmm);
+
+ if (mds->sessionmap.get_version() != cmapv) {
derr << "sessionmap version " << mds->sessionmap.get_version()
<< " != cmapv " << cmapv << dendl;
mds->clog->error() << "failure replaying journal (EImportStart)";
ls.back()->accounted_rstat = *nls.front();
}
+/*
+ * client_metadata_t
+ */
+void client_metadata_t::encode(bufferlist& bl) const
+{
+ ENCODE_START(1, 1, bl);
+ encode(kv_map, bl);
+ ENCODE_FINISH(bl);
+}
+
+void client_metadata_t::decode(bufferlist::const_iterator& p)
+{
+ DECODE_START(1, p);
+ decode(kv_map, p);
+ DECODE_FINISH(p);
+}
+
/*
* session_info_t
*/
encode(completed_requests, bl);
encode(prealloc_inos, bl); // hacky, see below.
encode(used_inos, bl);
- encode(client_metadata, bl);
+ encode(client_metadata.kv_map, bl);
encode(completed_flushes, bl);
encode(auth_name, bl);
ENCODE_FINISH(bl);
prealloc_inos.insert(used_inos);
used_inos.clear();
if (struct_v >= 4) {
- decode(client_metadata, p);
+ decode(client_metadata.kv_map, p);
}
if (struct_v >= 5) {
decode(completed_flushes, p);
}
f->close_section();
- for (map<string, string>::const_iterator i = client_metadata.begin();
- i != client_metadata.end(); ++i) {
- f->dump_string(i->first.c_str(), i->second);
+ for (auto& p : client_metadata) {
+ f->dump_string(p.first.c_str(), p.second);
}
}
return out << "old_rstat(first " << o.first << " " << o.rstat << " " << o.accounted_rstat << ")";
}
+/*
+ * client_metadata_t
+ */
+struct client_metadata_t {
+ using kv_map_t = std::map<std::string,std::string>;
+ using iterator = kv_map_t::const_iterator;
+
+ kv_map_t kv_map;
+
+ client_metadata_t() {}
+ client_metadata_t(const client_metadata_t& other) :
+ kv_map(other.kv_map) {}
+ client_metadata_t(client_metadata_t&& other) :
+ kv_map(std::move(other.kv_map)) {}
+ client_metadata_t(kv_map_t&& kv) :
+ kv_map(std::move(kv)) {}
+ client_metadata_t& operator=(const client_metadata_t& other) {
+ kv_map = other.kv_map;
+ return *this;
+ }
+
+ bool empty() const { return kv_map.empty(); }
+ iterator find(const std::string& key) const { return kv_map.find(key); }
+ iterator begin() const { return kv_map.begin(); }
+ iterator end() const { return kv_map.end(); }
+ std::string& operator[](const std::string& key) { return kv_map[key]; }
+ void merge(const client_metadata_t& other) {
+ kv_map.insert(other.kv_map.begin(), other.kv_map.end());
+ }
+
+ void encode(bufferlist& bl) const;
+ void decode(bufferlist::const_iterator& p);
+};
+WRITE_CLASS_ENCODER(client_metadata_t)
/*
* session_info_t
*/
-
struct session_info_t {
entity_inst_t inst;
std::map<ceph_tid_t,inodeno_t> completed_requests;
interval_set<inodeno_t> prealloc_inos; // preallocated, ready to use.
interval_set<inodeno_t> used_inos; // journaling use
- std::map<std::string, std::string> client_metadata;
+ client_metadata_t client_metadata;
std::set<ceph_tid_t> completed_flushes;
EntityName auth_name;
class MExportCaps : public Message {
+ static const int HEAD_VERSION = 2;
+ static const int COMPAT_VERSION = 1;
public:
inodeno_t ino;
bufferlist cap_bl;
map<client_t,entity_inst_t> client_map;
+ map<client_t,client_metadata_t> client_metadata_map;
MExportCaps() :
- Message(MSG_MDS_EXPORTCAPS) {}
+ Message(MSG_MDS_EXPORTCAPS, HEAD_VERSION, COMPAT_VERSION) {}
private:
~MExportCaps() override {}
encode(ino, payload);
encode(cap_bl, payload);
encode(client_map, payload, features);
+ encode(client_metadata_map, payload);
}
void decode_payload() override {
auto p = payload.cbegin();
decode(ino, p);
decode(cap_bl, p);
decode(client_map, p);
+ if (header.version >= 2)
+ decode(client_metadata_map, p);
}
};
class MMDSCacheRejoin : public Message {
- static const int HEAD_VERSION = 1;
+ static const int HEAD_VERSION = 2;
static const int COMPAT_VERSION = 1;
public:
// open
map<inodeno_t,map<client_t, cap_reconnect_t> > cap_exports;
map<client_t, entity_inst_t> client_map;
+ map<client_t,client_metadata_t> client_metadata_map;
bufferlist imported_caps;
// full
encode(strong_dentries, payload);
encode(authpinned_dentries, payload);
encode(xlocked_dentries, payload);
+ encode(client_metadata_map, payload);
}
void decode_payload() override {
auto p = payload.cbegin();
decode(strong_dentries, p);
decode(authpinned_dentries, p);
decode(xlocked_dentries, p);
+ if (header.version >= 2)
+ decode(client_metadata_map, p);
}
};
std::stringstream ss;
int r = filter.parse({"client_metadata.root=/rhubarb"}, &ss);
ASSERT_EQ(r, 0);
+ client_metadata_t meta;
Session *a = new Session();
- a->set_client_metadata({{"root", "/rhubarb"}});
+ meta.kv_map = {{"root", "/rhubarb"}};
+ a->set_client_metadata(meta);
Session *b = new Session();
- b->set_client_metadata({{"root", "/custard"}});
+ meta.kv_map = {{"root", "/custard"}};
+ b->set_client_metadata(meta);
ASSERT_TRUE(filter.match(*a, [](client_t c) -> bool {return false;}));
ASSERT_FALSE(filter.match(*b, [](client_t c) -> bool {return false;}));