]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: make Server::prepare_force_open_sessions() update client metadata
authorYan, Zheng <zyan@redhat.com>
Tue, 13 Mar 2018 11:19:04 +0000 (19:19 +0800)
committerYan, Zheng <zyan@redhat.com>
Thu, 12 Jul 2018 14:08:44 +0000 (22:08 +0800)
The function is used for opening sessions for importing caps. It didn't
set client metadata for new sessions.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
17 files changed:
src/mds/MDCache.cc
src/mds/MDCache.h
src/mds/MDSRank.cc
src/mds/Migrator.cc
src/mds/Migrator.h
src/mds/Server.cc
src/mds/Server.h
src/mds/SessionMap.cc
src/mds/SessionMap.h
src/mds/events/ESession.h
src/mds/events/ESessions.h
src/mds/journal.cc
src/mds/mdstypes.cc
src/mds/mdstypes.h
src/messages/MExportCaps.h
src/messages/MMDSCacheRejoin.h
src/test/mds/TestSessionFilter.cc

index c50ea99db247ef1a3e59f55f217db2472d5835a4..974e9f242476655d15a09f57dffb13224e6080a4 100644 (file)
@@ -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<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;
+      }
     }
   }
   
@@ -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;
     }
 
index ce1386ca0fade760eab8f7d34b5b8e1cc8df1fd6..3a72b65ffc7903c5af3ade6dcd9e87f23a06e616 100644 (file)
@@ -553,7 +553,9 @@ protected:
   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
index 017d103a73a43cd025197dc78a7c2ee17bf72337..3abc9a1cd76a5f9cb24bc47dbc072f8277a9a316 100644 (file)
@@ -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<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());
@@ -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<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
index fa79c0456d9a74c54985daa1896c6c3a7823e3ce..3bfcc4727a26617a0fb8c7a275cf3255aa9ff84d 100644 (file)
@@ -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<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;
@@ -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<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()));
@@ -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<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;
 
@@ -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<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;
 
@@ -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<CDir*> 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_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;
@@ -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_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();
@@ -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();
 
index ee2509b6e25083b8f8346cf3d3238ba21443900c..5e1a2693b63aed2001ec13bad96934032a39b9c0 100644 (file)
@@ -305,9 +305,11 @@ public:
   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);
@@ -317,7 +319,8 @@ public:
 
   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);
index 5ea6c8ebe7155b089fb6af0e2d67d5267699a060..df01ca5005af961084e5ba5e25b72fcba7db6972 100644 (file)
@@ -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<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:
@@ -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<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();
@@ -599,11 +602,12 @@ version_t Server::prepare_force_open_sessions(map<client_t,entity_inst_t>& 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<client_t,entity_inst_t>& 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_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,
@@ -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<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;
     }
index bb7e43f30769f241626a7ef3ba8b7f58a284be82..e21beb8bfc20dedbeaf88772b8e1c01231214f09 100644 (file)
@@ -116,6 +116,7 @@ public:
   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);
index b1c874e89a5e17c1a0065c17ce2c9fd17794b0c3..b11aa11835e05f715f014bb585ea935b45c660af 100644 (file)
@@ -843,7 +843,7 @@ void Session::clear_recalled_at()
   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;
 
@@ -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;
     }
   }
index 730f2cbf85f0ef597edb4d54601d5c9600f4ade0..f2fd342f6c9169eb4f254b6ec2d176c5cf33ecf4 100644 (file)
@@ -124,7 +124,7 @@ public:
     }
   }
   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
@@ -554,11 +554,16 @@ public:
        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);
     }
index 4cf348017c64a2ec30100933ffe9064238a1575e..c3b7c70f67cb7ddef7cfd2c9b47785159354f77d 100644 (file)
@@ -30,26 +30,19 @@ class ESession : public LogEvent {
   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;
index 0b29b53794b1e12696d54b6f3fadc62e2a043019..aa0eeff8158b0a2783b5085983014e228f5f5079 100644 (file)
 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; }
 
index 585f25a262c5a5aa7bd10a13b5bd68538a6a92a1..741a58f345c0695c8b6bff05c02345064fabce6d 100644 (file)
@@ -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<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
 }
@@ -1773,10 +1774,11 @@ void ESession::generate_test_instances(list<ESession*>& 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<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);
     }
   }
@@ -2944,12 +2951,15 @@ void EImportStart::replay(MDSRank *mds)
     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)";
index 24efe436b50642ca66b568cb3a65775ee23064e0..c0fcb85e31f7d7d84f65bc84035b93c1f78506f3 100644 (file)
@@ -365,6 +365,23 @@ void old_rstat_t::generate_test_instances(list<old_rstat_t*>& 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<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);
   }
 }
 
index 2a9f894ac0d659730da1501332952321a4c84b01..b00bb862d5d09774ee4ab11aefc7b134abf2cd24 100644 (file)
@@ -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<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;
 
index 5fc1b74bb2ef9a90c66560dedfd4dbbf5be04fcf..6d80b2eff82f2ae6c177d06269e82dfb41d70653 100644 (file)
 
 
 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 {}
 
@@ -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);
   }
 
 };
index 53e5dd91caba102eaa23f3406ceab03165ef19fe..ead58765a559572defdd5d34705f076a48a1748e 100644 (file)
@@ -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<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
@@ -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);
   }
 
 };
index 29ce49256be849c663cb534586ebde982a6ab975..39970a76df3371042a9a7eba8c97692b5e7bb386 100644 (file)
@@ -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;}));