]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: include last modification time and change attr of a snap realm node in snap...
authorVenky Shankar <vshankar@redhat.com>
Thu, 20 Oct 2022 10:04:08 +0000 (06:04 -0400)
committerVenky Shankar <vshankar@redhat.com>
Wed, 28 Feb 2024 13:42:30 +0000 (08:42 -0500)
To handle older clients, introduce a cephfs feature bit. The MDS encodes a "new"
SNapRealmInfo structure for clients supporting this feature (which includes the
last modification timestamp and a version/change_attr for the snap realm). For
clients not advertising this feature, the MDS uses the existing SnapRealmInfo
structure for snapshot traces.

Signed-off-by: Venky Shankar <vshankar@redhat.com>
(cherry picked from commit 7a4c509f7289ff4b400eb8cae462f882de3cab3b)

src/common/snap_types.cc
src/common/snap_types.h
src/mds/MDCache.cc
src/mds/Server.cc
src/mds/Server.h
src/mds/SnapRealm.cc
src/mds/SnapRealm.h
src/mds/cephfs_features.h

index 521404ca2b5b028b22128c224e3d65f5428026f6..dc634907b8ae61921bcfcc3eaaeaf16a8591052c 100644 (file)
@@ -53,6 +53,46 @@ void SnapRealmInfo::generate_test_instances(std::list<SnapRealmInfo*>& o)
   o.back()->prior_parent_snaps.push_back(5);
 }
 
+// -- "new" SnapRealmInfo --
+
+void SnapRealmInfoNew::encode(ceph::buffer::list& bl) const
+{
+  using ceph::encode;
+  ENCODE_START(1, 1, bl);
+  encode(info, bl);
+  encode(last_modified, bl);
+  encode(change_attr, bl);
+  ENCODE_FINISH(bl);
+}
+
+void SnapRealmInfoNew::decode(ceph::buffer::list::const_iterator& bl)
+{
+  using ceph::decode;
+  DECODE_START(1, bl);
+  decode(info, bl);
+  decode(last_modified, bl);
+  decode(change_attr, bl);
+  DECODE_FINISH(bl);
+}
+
+void SnapRealmInfoNew::dump(ceph::Formatter *f) const
+{
+  info.dump(f);
+  f->dump_stream("last_modified") << last_modified;
+  f->dump_unsigned("change_attr", change_attr);
+}
+
+void SnapRealmInfoNew::generate_test_instances(std::list<SnapRealmInfoNew*>& o)
+{
+  o.push_back(new SnapRealmInfoNew);
+  o.push_back(new SnapRealmInfoNew(SnapRealmInfo(1, 10, 10, 0), utime_t(), 0));
+  o.push_back(new SnapRealmInfoNew(SnapRealmInfo(1, 10, 10, 0), utime_t(), 1));
+  o.back()->info.my_snaps.push_back(10);
+  o.push_back(new SnapRealmInfoNew(SnapRealmInfo(1, 10, 10, 5), utime_t(), 2));
+  o.back()->info.my_snaps.push_back(10);
+  o.back()->info.prior_parent_snaps.push_back(3);
+  o.back()->info.prior_parent_snaps.push_back(5);
+}
 
 // -----
 
index 958aea339a183ec92cb95d14985d433ed908f012..b71fe9780054841046f40693b820599fb961de17 100644 (file)
@@ -2,6 +2,7 @@
 #define __CEPH_SNAP_TYPES_H
 
 #include "include/types.h"
+#include "include/utime.h"
 #include "include/fs_types.h"
 
 namespace ceph {
@@ -39,6 +40,35 @@ struct SnapRealmInfo {
 };
 WRITE_CLASS_ENCODER(SnapRealmInfo)
 
+// "new* snap realm info - carries additional metadata (last modified,
+// change_attr) and is version encoded.
+struct SnapRealmInfoNew {
+  SnapRealmInfo info;
+  utime_t last_modified;
+  uint64_t change_attr;
+
+  SnapRealmInfoNew() {
+  }
+
+  SnapRealmInfoNew(const SnapRealmInfo &info_, utime_t last_modified_, uint64_t change_attr_) {
+    // FIPS zeroization audit 20191115: this memset is not security related.
+    info = info_;
+    last_modified = last_modified_;
+    change_attr = change_attr_;
+  }
+
+  inodeno_t ino() const { return inodeno_t(info.h.ino); }
+  inodeno_t parent() const { return inodeno_t(info.h.parent); }
+  snapid_t seq() const { return snapid_t(info.h.seq); }
+  snapid_t parent_since() const { return snapid_t(info.h.parent_since); }
+  snapid_t created() const { return snapid_t(info.h.created); }
+
+  void encode(ceph::buffer::list& bl) const;
+  void decode(ceph::buffer::list::const_iterator& bl);
+  void dump(ceph::Formatter *f) const;
+  static void generate_test_instances(std::list<SnapRealmInfoNew*>& o);
+};
+WRITE_CLASS_ENCODER(SnapRealmInfoNew)
 
 struct SnapContext {
   snapid_t seq;            // 'time' stamp
index 2a1277d9e0ec47a46ce7726fd3728ee2422c53f5..6bed127e2b9643d5247b05ebbebc33921d545480 100644 (file)
@@ -5638,7 +5638,7 @@ void MDCache::prepare_realm_split(SnapRealm *realm, client_t client, inodeno_t i
     snap = make_message<MClientSnap>(CEPH_SNAP_OP_SPLIT);
     splits.emplace(std::piecewise_construct, std::forward_as_tuple(client), std::forward_as_tuple(snap));
     snap->head.split = realm->inode->ino();
-    snap->bl = realm->get_snap_trace();
+    snap->bl = mds->server->get_snap_trace(client, realm);
 
     for (const auto& child : realm->open_children)
       snap->split_realms.push_back(child->inode->ino());
@@ -5669,7 +5669,7 @@ void MDCache::prepare_realm_merge(SnapRealm *realm, SnapRealm *parent_realm,
       update->head.split = parent_realm->inode->ino();
       update->split_inos = split_inos;
       update->split_realms = split_realms;
-      update->bl = parent_realm->get_snap_trace();
+      update->bl = mds->server->get_snap_trace(p.first, parent_realm);
       em.first->second = std::move(update);
     }
   }
@@ -5866,7 +5866,7 @@ void MDCache::do_cap_import(Session *session, CInode *in, Capability *cap,
                                        cap->get_last_seq(), cap->pending(), cap->wanted(),
                                        0, cap->get_mseq(), mds->get_osd_epoch_barrier());
   in->encode_cap_message(reap, cap);
-  reap->snapbl = realm->get_snap_trace();
+  reap->snapbl = mds->server->get_snap_trace(session, realm);
   reap->set_cap_peer(p_cap_id, p_seq, p_mseq, peer, p_flags);
   mds->send_message_client_counted(reap, session);
 }
@@ -6033,7 +6033,7 @@ void MDCache::finish_snaprealm_reconnect(client_t client, SnapRealm *realm, snap
     dout(10) << "finish_snaprealm_reconnect client." << client << " has old seq " << seq << " < " 
             << realm->get_newest_seq() << " on " << *realm << dendl;
     auto snap = make_message<MClientSnap>(CEPH_SNAP_OP_UPDATE);
-    snap->bl = realm->get_snap_trace();
+    snap->bl = mds->server->get_snap_trace(client, realm);
     updates.emplace(std::piecewise_construct, std::forward_as_tuple(client), std::forward_as_tuple(snap));
   } else {
     dout(10) << "finish_snaprealm_reconnect client." << client << " up to date"
@@ -9812,7 +9812,7 @@ void MDCache::do_realm_invalidate_and_update_notify(CInode *in, int snapop, bool
          update->head.split = in->ino();
          update->split_inos = split_inos;
          update->split_realms = split_realms;
-         update->bl = in->snaprealm->get_snap_trace();
+         update->bl = mds->server->get_snap_trace(em.first->first, in->snaprealm);
          em.first->second = std::move(update);
        }
       }
@@ -9906,7 +9906,7 @@ void MDCache::notify_global_snaprealm_update(int snap_op)
       continue;
     auto update = make_message<MClientSnap>(snap_op);
     update->head.split = global_snaprealm->inode->ino();
-    update->bl = global_snaprealm->get_snap_trace();
+    update->bl = mds->server->get_snap_trace(session, global_snaprealm);
     mds->send_message_client_counted(update, session);
   }
 }
index f50775665083e1b4d0957a9dad9b8e91fee62c57..8a07d5c85ce5405dc31f2d3df75efa2dc732327e 100644 (file)
@@ -2356,7 +2356,7 @@ void Server::set_trace_dist(const ref_t<MClientReply> &reply,
       realm = in->find_snaprealm();
     else
       realm = dn->get_dir()->get_inode()->find_snaprealm();
-    reply->snapbl = realm->get_snap_trace();
+    reply->snapbl = get_snap_trace(session, realm);
     dout(10) << "set_trace_dist snaprealm " << *realm << " len=" << reply->snapbl.length() << dendl;
   }
 
@@ -4881,7 +4881,7 @@ void Server::handle_client_readdir(MDRequestRef& mdr)
   //  this isn't perfect, but we should capture the main variable/unbounded size items!
   int front_bytes = dirbl.length() + sizeof(__u32) + sizeof(__u8)*2;
   int bytes_left = max_bytes - front_bytes;
-  bytes_left -= realm->get_snap_trace().length();
+  bytes_left -= get_snap_trace(session, realm).length();
 
   // build dir contents
   bufferlist dnbl;
@@ -11418,3 +11418,18 @@ void Server::dump_reconnect_status(Formatter *f) const
   f->dump_stream("client_reconnect_gather") << client_reconnect_gather;
   f->close_section();
 }
+
+const bufferlist& Server::get_snap_trace(Session *session, SnapRealm *realm) const {
+  ceph_assert(session);
+  ceph_assert(realm);
+  if (session->info.has_feature(CEPHFS_FEATURE_NEW_SNAPREALM_INFO)) {
+    return realm->get_snap_trace_new();
+  } else {
+    return realm->get_snap_trace();
+  }
+}
+
+const bufferlist& Server::get_snap_trace(client_t client, SnapRealm *realm) const {
+  Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(client.v));
+  return get_snap_trace(session, realm);
+}
index afd7c342d5023d9dc14bffce4a9dba8c5d9ef8c4..f33445c9f9c345177d3015d9b0cc605b3c8b4825 100644 (file)
@@ -340,6 +340,9 @@ public:
     laggy_clients.clear();
   }
 
+  const bufferlist& get_snap_trace(Session *session, SnapRealm *realm) const;
+  const bufferlist& get_snap_trace(client_t client, SnapRealm *realm) const;
+
 private:
   friend class MDSContinuation;
   friend class ServerContext;
index 9a81511adc7b41b92544dec1e2940a4b5fa2b73a..c7a7d75bc242d0608731bdb1c04e83fa0f26641e 100644 (file)
@@ -390,9 +390,16 @@ const bufferlist& SnapRealm::get_snap_trace() const
   return cached_snap_trace;
 }
 
+const bufferlist& SnapRealm::get_snap_trace_new() const
+{
+  check_cache();
+  return cached_snap_trace_new;
+}
+
 void SnapRealm::build_snap_trace() const
 {
   cached_snap_trace.clear();
+  cached_snap_trace_new.clear();
 
   if (global) {
     SnapRealmInfo info(inode->ino(), 0, cached_seq, 0);
@@ -401,7 +408,10 @@ void SnapRealm::build_snap_trace() const
       info.my_snaps.push_back(*p);
 
     dout(10) << "build_snap_trace my_snaps " << info.my_snaps << dendl;
+
+    SnapRealmInfoNew ninfo(info, srnode.last_modified, srnode.change_attr);
     encode(info, cached_snap_trace);
+    encode(ninfo, cached_snap_trace_new);
     return;
   }
 
@@ -434,10 +444,15 @@ void SnapRealm::build_snap_trace() const
     info.my_snaps.push_back(p->first);
   dout(10) << "build_snap_trace my_snaps " << info.my_snaps << dendl;
 
+  SnapRealmInfoNew ninfo(info, srnode.last_modified, srnode.change_attr);
+
   encode(info, cached_snap_trace);
+  encode(ninfo, cached_snap_trace_new);
 
-  if (parent)
+  if (parent) {
     cached_snap_trace.append(parent->get_snap_trace());
+    cached_snap_trace_new.append(parent->get_snap_trace_new());
+  }
 }
 
 void SnapRealm::prune_past_parent_snaps()
index 7ddffe0ba9a853893f27d7eeacb42a19fc500d16..700c1d81e3b574db992037d8ad0047e23f440529 100644 (file)
@@ -45,6 +45,7 @@ public:
   void get_snap_info(std::map<snapid_t, const SnapInfo*>& infomap, snapid_t first=0, snapid_t last=CEPH_NOSNAP);
 
   const ceph::buffer::list& get_snap_trace() const;
+  const ceph::buffer::list& get_snap_trace_new() const;
   void build_snap_trace() const;
 
   std::string_view get_snapname(snapid_t snapid, inodeno_t atino);
@@ -143,6 +144,7 @@ private:
   mutable std::set<snapid_t> cached_snaps;
   mutable SnapContext cached_snap_context;
   mutable ceph::buffer::list cached_snap_trace;
+  mutable ceph::buffer::list cached_snap_trace_new;
   mutable inodeno_t cached_subvolume_ino = 0;
 };
 
index 6fe114274bb61e4da321e909e8843c3509ed0e4b..83f9104d4236304ad532f8788b4896376ae6413a 100644 (file)
@@ -68,6 +68,7 @@ namespace ceph {
   CEPHFS_FEATURE_NOTIFY_SESSION_STATE,  \
   CEPHFS_FEATURE_OP_GETVXATTR,          \
   CEPHFS_FEATURE_32BITS_RETRY_FWD,      \
+  CEPHFS_FEATURE_NEW_SNAPREALM_INFO,   \
   CEPHFS_FEATURE_HAS_OWNER_UIDGID,      \
 }