From: Yan, Zheng Date: Tue, 13 Mar 2018 11:19:04 +0000 (+0800) Subject: mds: make Server::prepare_force_open_sessions() update client metadata X-Git-Tag: v14.0.1~879^2~8 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=c7400000440d224b62c946757c2fc990d60ddcb7;p=ceph.git mds: make Server::prepare_force_open_sessions() update client metadata The function is used for opening sessions for importing caps. It didn't set client metadata for new sessions. Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index c50ea99db247e..974e9f2424766 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -4045,12 +4045,13 @@ void MDCache::rejoin_send_rejoins() for (auto q = p->second.second.begin(); q != p->second.second.end(); ++q) client_exports[q->first].insert(target); } - for (map >::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::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; + } } } @@ -4421,6 +4422,8 @@ void MDCache::handle_cache_rejoin_weak(MMDSCacheRejoin *weak) // 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); @@ -5446,10 +5449,14 @@ bool MDCache::process_imported_caps() 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; } diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index ce1386ca0fade..3a72b65ffc790 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -553,7 +553,9 @@ protected: set rejoin_ack_gather; // nodes from whom i need a rejoin ack map > > rejoin_imported_caps; map > > rejoin_slave_exports; + map rejoin_client_map; + map rejoin_client_metadata_map; map > rejoin_session_map; map > > cap_exports; // ino -> target, client -> capex diff --git a/src/mds/MDSRank.cc b/src/mds/MDSRank.cc index 017d103a73a43..3abc9a1cd76a5 100644 --- a/src/mds/MDSRank.cc +++ b/src/mds/MDSRank.cc @@ -2206,21 +2206,19 @@ void MDSRankDispatcher::dump_sessions(const SessionFilter &filter, Formatter *f) // Dump sessions, decorated with recovery/replay status f->open_array_section("sessions"); const ceph::unordered_map session_map = sessionmap.get_sessions(); - for (ceph::unordered_map::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()); @@ -2228,12 +2226,11 @@ void MDSRankDispatcher::dump_sessions(const SessionFilter &filter, Formatter *f) 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::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 diff --git a/src/mds/Migrator.cc b/src/mds/Migrator.cc index fa79c0456d9a7..3bfcc4727a266 100644 --- a/src/mds/Migrator.cc +++ b/src/mds/Migrator.cc @@ -1414,11 +1414,13 @@ void Migrator::export_go_synced(CDir *dir, uint64_t tid) // fill export message with cache data MExportDir *req = new MExportDir(dir->dirfrag(), it->second.tid); map exported_client_map; + map 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 bounds; @@ -1451,7 +1453,8 @@ void Migrator::export_go_synced(CDir *dir, uint64_t tid) * is pretty arbitrary and dumb. */ void Migrator::encode_export_inode(CInode *in, bufferlist& enc_state, - map& exported_client_map) + map& exported_client_map, + map& exported_client_metadata_map) { dout(7) << "encode_export_inode " << *in << dendl; assert(!in->is_replica(mds->get_nodeid())); @@ -1467,11 +1470,12 @@ void Migrator::encode_export_inode(CInode *in, bufferlist& enc_state, 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& exported_client_map) + map& exported_client_map, + map& exported_client_metadata_map) { dout(20) << "encode_export_inode_caps " << *in << dendl; @@ -1488,7 +1492,11 @@ void Migrator::encode_export_inode_caps(CInode *in, bool auth_cap, bufferlist& b // 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; } } @@ -1567,7 +1575,8 @@ void Migrator::finish_export_inode(CInode *in, mds_rank_t peer, uint64_t Migrator::encode_export_dir(bufferlist& exportbl, CDir *dir, - map& exported_client_map) + map& exported_client_map, + map& exported_client_metadata_map) { uint64_t num_exported = 0; @@ -1632,7 +1641,7 @@ uint64_t Migrator::encode_export_dir(bufferlist& exportbl, // -- 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 dfs; @@ -1649,7 +1658,7 @@ uint64_t Migrator::encode_export_dir(bufferlist& exportbl, // 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; } @@ -2485,10 +2494,14 @@ void Migrator::handle_export_dir(MExportDir *m) // include imported sessions in EImportStart auto cmp = m->client_map.cbegin(); map client_map; + map 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; @@ -3287,7 +3300,7 @@ void Migrator::export_caps(CInode *in) 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); } @@ -3382,12 +3395,14 @@ void Migrator::handle_export_caps(MExportCaps *ex) in->auth_pin(this); map client_map; + map 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(); @@ -3395,8 +3410,8 @@ void Migrator::handle_export_caps(MExportCaps *ex) 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(); diff --git a/src/mds/Migrator.h b/src/mds/Migrator.h index ee2509b6e2508..5e1a2693b63ae 100644 --- a/src/mds/Migrator.h +++ b/src/mds/Migrator.h @@ -305,9 +305,11 @@ public: void get_export_client_set(CInode *in, set &client_set); void encode_export_inode(CInode *in, bufferlist& bl, - map& exported_client_map); + map& exported_client_map, + map& exported_client_metadata_map); void encode_export_inode_caps(CInode *in, bool auth_cap, bufferlist& bl, - map& exported_client_map); + map& exported_client_map, + map& exported_client_metadata_map); void finish_export_inode(CInode *in, mds_rank_t target, map& peer_imported, list& finished); @@ -317,7 +319,8 @@ public: uint64_t encode_export_dir(bufferlist& exportbl, CDir *dir, - map& exported_client_map); + map& exported_client_map, + map& exported_client_metadata_map); void finish_export_dir(CDir *dir, mds_rank_t target, map >& peer_imported, list& finished, int *num_dentries); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 5ea6c8ebe7155..df01ca5005af9 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -338,9 +338,6 @@ void Server::handle_client_session(MClientSession *m) 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; } @@ -365,43 +362,48 @@ void Server::handle_client_session(MClientSession *m) 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::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: @@ -590,6 +592,7 @@ void Server::_session_logged(Session *session, uint64_t state_seq, bool open, ve * - sessions learned from other MDSs during a cross-MDS rename */ version_t Server::prepare_force_open_sessions(map& cm, + map& cmm, map >& smap) { version_t pv = mds->sessionmap.get_projected(); @@ -599,11 +602,12 @@ version_t Server::prepare_force_open_sessions(map& cm, << 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; @@ -619,6 +623,9 @@ version_t Server::prepare_force_open_sessions(map& cm, 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() || @@ -7387,9 +7394,13 @@ version_t Server::_rename_prepare_import(MDRequestRef& mdr, CDentry *srcdn, buff // imported caps map client_map; + map 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 updated_scatterlocks; mdcache->migrator->decode_import_inode(srcdn, blp, srcdn->authority().first, mdr->ls, @@ -8262,23 +8273,26 @@ void Server::_logged_slave_rename(MDRequestRef& mdr, // export srci? if (srcdn->is_auth() && srcdnl->is_primary()) { // set export bounds for CInode::encode_export() - list bounds; - if (srcdnl->get_inode()->is_dir()) { - srcdnl->get_inode()->get_dirfrags(bounds); - for (list::iterator p = bounds.begin(); p != bounds.end(); ++p) - (*p)->state_set(CDir::STATE_EXPORTBOUND); - } + if (reply) { + list bounds; + if (srcdnl->get_inode()->is_dir()) { + srcdnl->get_inode()->get_dirfrags(bounds); + for (list::iterator p = bounds.begin(); p != bounds.end(); ++p) + (*p)->state_set(CDir::STATE_EXPORTBOUND); + } - map exported_client_map; - bufferlist inodebl; - mdcache->migrator->encode_export_inode(srcdnl->get_inode(), inodebl, - exported_client_map); + map exported_client_map; + map exported_client_metadata_map; + bufferlist inodebl; + mdcache->migrator->encode_export_inode(srcdnl->get_inode(), inodebl, + exported_client_map, + exported_client_metadata_map); - for (list::iterator p = bounds.begin(); p != bounds.end(); ++p) - (*p)->state_clear(CDir::STATE_EXPORTBOUND); + for (list::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; } diff --git a/src/mds/Server.h b/src/mds/Server.h index bb7e43f30769f..e21beb8bfc20d 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -116,6 +116,7 @@ public: void _session_logged(Session *session, uint64_t state_seq, bool open, version_t pv, interval_set& inos,version_t piv); version_t prepare_force_open_sessions(map &cm, + map& cmm, map >& smap); void finish_force_open_sessions(const map >& smap, bool dec_import=true); diff --git a/src/mds/SessionMap.cc b/src/mds/SessionMap.cc index b1c874e89a5e1..b11aa11835e05 100644 --- a/src/mds/SessionMap.cc +++ b/src/mds/SessionMap.cc @@ -843,7 +843,7 @@ void Session::clear_recalled_at() recall_release_count = 0; } -void Session::set_client_metadata(map const &meta) +void Session::set_client_metadata(const client_metadata_t& meta) { info.client_metadata = meta; @@ -1011,10 +1011,11 @@ bool SessionFilter::match( 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; } } diff --git a/src/mds/SessionMap.h b/src/mds/SessionMap.h index 730f2cbf85f0e..f2fd342f6c916 100644 --- a/src/mds/SessionMap.h +++ b/src/mds/SessionMap.h @@ -124,7 +124,7 @@ public: } } void decode(bufferlist::const_iterator &p); - void set_client_metadata(std::map 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 @@ -554,11 +554,16 @@ public: s.insert(p->second); } - void replay_open_sessions(map& client_map) { + void replay_open_sessions(map& client_map, + map& client_metadata_map) { for (map::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); } diff --git a/src/mds/events/ESession.h b/src/mds/events/ESession.h index 4cf348017c64a..c3b7c70f67cb7 100644 --- a/src/mds/events/ESession.h +++ b/src/mds/events/ESession.h @@ -30,26 +30,19 @@ class ESession : public LogEvent { version_t inotablev{0}; // Client metadata stored during open - std::map 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 &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& 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; diff --git a/src/mds/events/ESessions.h b/src/mds/events/ESessions.h index 0b29b53794b1e..aa0eeff8158b0 100644 --- a/src/mds/events/ESessions.h +++ b/src/mds/events/ESessions.h @@ -23,18 +23,19 @@ class ESessions : public LogEvent { protected: version_t cmapv; // client map version + bool old_style_encode; public: map client_map; - bool old_style_encode; + map client_metadata_map; ESessions() : LogEvent(EVENT_SESSIONS), cmapv(0), old_style_encode(false) { } - ESessions(version_t pv, map& cm) : + ESessions(version_t pv, map&& cm, + map&& 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; } diff --git a/src/mds/journal.cc b/src/mds/journal.cc index 585f25a262c5a..741a58f345c06 100644 --- a/src/mds/journal.cc +++ b/src/mds/journal.cc @@ -1721,7 +1721,7 @@ void ESession::replay(MDSRank *mds) 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); @@ -1734,7 +1734,7 @@ void ESession::encode(bufferlist &bl, uint64_t features) const 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); @@ -1742,7 +1742,9 @@ void ESession::decode(bufferlist::const_iterator &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); @@ -1756,9 +1758,8 @@ void ESession::dump(Formatter *f) const f->dump_stream("inos") << inos; f->dump_int("inotable version", inotablev); f->open_object_section("client_metadata"); - for (map::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 } @@ -1773,10 +1774,11 @@ void ESession::generate_test_instances(list& ls) 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); } @@ -1791,11 +1793,12 @@ void ESessions::decode_old(bufferlist::const_iterator &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); } @@ -1832,7 +1835,7 @@ void ESessions::replay(MDSRank *mds) } 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(); @@ -2105,10 +2108,14 @@ void EUpdate::replay(MDSRank *mds) << " < " << cmapv << dendl; // open client sessions? map cm; + map 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); } } @@ -2944,12 +2951,15 @@ void EImportStart::replay(MDSRank *mds) dout(10) << "EImportStart.replay sessionmap " << mds->sessionmap.get_version() << " < " << cmapv << dendl; map cm; + map 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)"; diff --git a/src/mds/mdstypes.cc b/src/mds/mdstypes.cc index 24efe436b5064..c0fcb85e31f7d 100644 --- a/src/mds/mdstypes.cc +++ b/src/mds/mdstypes.cc @@ -365,6 +365,23 @@ void old_rstat_t::generate_test_instances(list& ls) 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 */ @@ -375,7 +392,7 @@ void session_info_t::encode(bufferlist& bl, uint64_t features) const 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); @@ -400,7 +417,7 @@ void session_info_t::decode(bufferlist::const_iterator& p) 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); @@ -448,9 +465,8 @@ void session_info_t::dump(Formatter *f) const } f->close_section(); - for (map::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); } } diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index 2a9f894ac0d65..b00bb862d5d09 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -1059,17 +1059,50 @@ inline std::ostream& operator<<(std::ostream& out, const old_rstat_t& o) { 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; + 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 completed_requests; interval_set prealloc_inos; // preallocated, ready to use. interval_set used_inos; // journaling use - std::map client_metadata; + client_metadata_t client_metadata; std::set completed_flushes; EntityName auth_name; diff --git a/src/messages/MExportCaps.h b/src/messages/MExportCaps.h index 5fc1b74bb2ef9..6d80b2eff82f2 100644 --- a/src/messages/MExportCaps.h +++ b/src/messages/MExportCaps.h @@ -20,13 +20,16 @@ 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_map; + map client_metadata_map; MExportCaps() : - Message(MSG_MDS_EXPORTCAPS) {} + Message(MSG_MDS_EXPORTCAPS, HEAD_VERSION, COMPAT_VERSION) {} private: ~MExportCaps() override {} @@ -41,12 +44,15 @@ public: 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); } }; diff --git a/src/messages/MMDSCacheRejoin.h b/src/messages/MMDSCacheRejoin.h index 53e5dd91caba1..ead58765a5595 100644 --- a/src/messages/MMDSCacheRejoin.h +++ b/src/messages/MMDSCacheRejoin.h @@ -29,7 +29,7 @@ class MMDSCacheRejoin : public Message { - static const int HEAD_VERSION = 1; + static const int HEAD_VERSION = 2; static const int COMPAT_VERSION = 1; public: @@ -178,6 +178,7 @@ class MMDSCacheRejoin : public Message { // open map > cap_exports; map client_map; + map client_metadata_map; bufferlist imported_caps; // full @@ -323,6 +324,7 @@ public: 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(); @@ -347,6 +349,8 @@ public: decode(strong_dentries, p); decode(authpinned_dentries, p); decode(xlocked_dentries, p); + if (header.version >= 2) + decode(client_metadata_map, p); } }; diff --git a/src/test/mds/TestSessionFilter.cc b/src/test/mds/TestSessionFilter.cc index 29ce49256be84..39970a76df337 100644 --- a/src/test/mds/TestSessionFilter.cc +++ b/src/test/mds/TestSessionFilter.cc @@ -123,10 +123,13 @@ TEST(MDSSessionFilter, MetadataEquality) 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;}));