]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/osd: implement handling of RADOS' extended attirbutes in FastEC
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Thu, 27 Nov 2025 15:28:58 +0000 (15:28 +0000)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Tue, 27 Jan 2026 19:43:00 +0000 (19:43 +0000)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/crimson/osd/ec_backend.cc
src/crimson/osd/ec_backend.h
src/crimson/osd/object_context.h
src/crimson/osd/ops_executer.cc
src/crimson/osd/ops_executer.h
src/crimson/osd/pg_backend.cc
src/crimson/osd/pg_backend.h
src/crimson/osd/replicated_backend.cc
src/crimson/osd/replicated_backend.h

index 0e1ff7290059cff9cc64badc2a5e95736029928b..4517df37f1823fee3e71c4be2f0f8aa15e6467f7 100644 (file)
@@ -789,4 +789,13 @@ ECBackend::handle_rep_read_reply(ECSubReadReply& mop)
   return ll_read_ierrorator::now();
 }
 
+PGBackend::get_attr_ierrorator::future<ceph::bufferlist>
+ECBackend::getxattr(
+  const hobject_t& soid,
+  std::string&& key) const
+{
+  // ENOSUPP! ECBackend reads xattr solely from the ObjectContext::attr_cache
+  return crimson::ct_error::enodata::make();
+}
+
 } // namespace crimson::osd
index 7a60e276400aebff36226cbc28a76199216f06a0..996c366c06c90a7c8c6dda5a7a81cb2a0e174612 100644 (file)
@@ -51,6 +51,10 @@ public:
   ll_read_ierrorator::future<> handle_rep_read_reply(ECSubReadReply& mop);
   ll_read_ierrorator::future<> handle_rep_read_reply(Ref<MOSDECSubOpReadReply>);
 
+  PGBackend::get_attr_ierrorator::future<ceph::bufferlist> getxattr(
+    const hobject_t& soid,
+    std::string&& key) const final;
+
 private:
   friend class ECRecoveryBackend;
 
index 3714913a725350ff8a446e639f02409cff6ee7b2..1845cb179b3da7ab88a8b5273dc1f304eaae650f 100644 (file)
@@ -76,7 +76,8 @@ public:
   std::map<watch_key_t, seastar::shared_ptr<crimson::osd::Watch>> watchers;
 
   // attr cache. ECTransaction is the initial user
-  std::map<std::string, ceph::buffer::list, std::less<>> attr_cache;
+  using attr_cache_t = std::map<std::string, ceph::buffer::list, std::less<>>;
+  attr_cache_t attr_cache;
 
   CommonOBCPipeline obc_pipeline;
 
index 3b6819278aff3229eedb3673e382e981b0a1efa3..3a76a88ca319c00ae25b4d3d4ce071033ebf969b 100644 (file)
@@ -472,6 +472,17 @@ auto OpsExecuter::do_const_op(Func&& f) {
   return std::forward<Func>(f)(pg->get_backend(), std::as_const(obc->obs));
 }
 
+template <class Func>
+auto OpsExecuter::do_read_attr_cache(Func&& f) {
+  ++num_read;
+  // TODO: pass backend as read-only
+  return std::invoke(
+    std::forward<Func>(f),
+    pg->get_backend(),
+    std::as_const(obc->attr_cache),
+    std::as_const(obc->obs));
+}
+
 // Defined here because there is a circular dependency between OpsExecuter and PG
 template <class Func>
 auto OpsExecuter::do_write_op(Func&& f, OpsExecuter::modified_by m) {
@@ -617,12 +628,16 @@ OpsExecuter::do_execute_op(OSDOp& osd_op)
       return backend.cmp_ext(os, osd_op);
     });
   case CEPH_OSD_OP_GETXATTR:
-    return do_read_op([this, &osd_op](auto& backend, const auto& os) {
-      return backend.getxattr(os, osd_op, delta_stats);
+    return do_read_attr_cache([this, &osd_op](auto& backend,
+                                             const auto& attr_cache,
+                                             const auto& os) {
+      return backend.getxattr(os, attr_cache, osd_op, delta_stats);
     });
   case CEPH_OSD_OP_GETXATTRS:
-    return do_read_op([this, &osd_op](auto& backend, const auto& os) {
-      return backend.get_xattrs(os, osd_op, delta_stats);
+    return do_read_attr_cache([this, &osd_op](auto& backend,
+                                             const auto& attr_cache,
+                                             const auto& os) {
+      return backend.get_xattrs(os, attr_cache, osd_op, delta_stats);
     });
   case CEPH_OSD_OP_CMPXATTR:
     return do_read_op([this, &osd_op](auto& backend, const auto& os) {
index 00d9b1883da6a9bc15d62d1a59951b868dbcfc67..f78b29cef0e1cc54a0a7b674bc15ceca9963d5fc 100644 (file)
@@ -336,6 +336,9 @@ private:
     return do_const_op(std::forward<Func>(f));
   }
 
+  template <class Func>
+  auto do_read_attr_cache(Func&& f);
+
   template <class Func>
   auto do_snapset_op(Func&& f) {
     ++num_read;
index 1162f95ccb3583c598c1414a68ab546d32f62967..0e5d36648afade50aa0e1aae047dcd709d63772f 100644 (file)
@@ -1142,8 +1142,16 @@ PGBackend::get_attr_ierrorator::future<> PGBackend::getxattr(
     bp.copy(osd_op.op.xattr.name_len, aname);
     name = "_" + aname;
   }
-  logger().debug("getxattr on obj={} for attr={}", os.oi.soid, name);
-  return getxattr(os.oi.soid, std::move(name)).safe_then_interruptible(
+  auto get_attr_maybe_from_cache =
+    [&] () mutable -> get_attr_ierrorator::future<ceph::bufferlist> {
+    if (auto cache_it = attr_cache.find(name); cache_it != std::end(attr_cache)) {
+      return get_attr_ierrorator::make_ready_future<ceph::bufferlist>(
+        cache_it->second);
+    }
+    logger().debug("getxattr on obj={} for attr={}", os.oi.soid, name);
+    return getxattr(os.oi.soid, std::move(name));
+  };
+  return get_attr_maybe_from_cache().safe_then_interruptible(
     [&delta_stats, &osd_op] (ceph::bufferlist&& val) {
     osd_op.outdata = std::move(val);
     osd_op.op.xattr.value_len = osd_op.outdata.length();
@@ -1153,22 +1161,21 @@ PGBackend::get_attr_ierrorator::future<> PGBackend::getxattr(
   });
 }
 
-PGBackend::get_attr_ierrorator::future<ceph::bufferlist>
-PGBackend::getxattr(
-  const hobject_t& soid,
-  std::string&& key) const
-{
-  return seastar::do_with(key, [this, &soid](auto &key) {
-    return store->get_attr(coll, ghobject_t{soid}, key);
-  });
-}
-
 PGBackend::get_attr_ierrorator::future<> PGBackend::get_xattrs(
   const ObjectState& os,
+  const ObjectContext::attr_cache_t& attr_cache,
   OSDOp& osd_op,
   object_stat_sum_t& delta_stats) const
 {
-  return store->get_attrs(coll, ghobject_t{os.oi.soid}).safe_then(
+  auto get_attrs_maybe_from_cache =
+    [&] () {
+    if (!std::empty(attr_cache)) {
+      return crimson::os::FuturizedStore::Shard::get_attrs_ertr::make_ready_future<
+       crimson::os::FuturizedStore::Shard::attrs_t>(attr_cache);
+    }
+    return store->get_attrs(coll, ghobject_t{os.oi.soid});
+  };
+  return get_attrs_maybe_from_cache().safe_then(
     [&delta_stats, &osd_op](auto&& attrs) {
     std::vector<std::pair<std::string, bufferlist>> user_xattrs;
     ceph::bufferlist bl;
index ad7bf32492c39d1b20a08ecc61fd8fec1903d2f2..880b429b24b6cd0925d90ae672fc9c87f13bbbcc 100644 (file)
@@ -279,13 +279,15 @@ public:
       get_attr_errorator>;
   get_attr_ierrorator::future<> getxattr(
     const ObjectState& os,
+    const ObjectContext::attr_cache_t& attr_cache,
     OSDOp& osd_op,
     object_stat_sum_t& delta_stats) const;
-  get_attr_ierrorator::future<ceph::bufferlist> getxattr(
+  virtual get_attr_ierrorator::future<ceph::bufferlist> getxattr(
     const hobject_t& soid,
-    std::string&& key) const;
+    std::string&& key) const = 0;
   get_attr_ierrorator::future<> get_xattrs(
     const ObjectState& os,
+    const ObjectContext::attr_cache_t& attr_cache,
     OSDOp& osd_op,
     object_stat_sum_t& delta_stats) const;
   using cmp_xattr_errorator = get_attr_errorator::extend<
index e3d2414a5d67441c23af7457cf343f5f30dc2245..4f31c70665d0244bb78b68be15e1dccc0a5651b8 100644 (file)
@@ -361,4 +361,14 @@ void ReplicatedBackend::do_pct(const MOSDPGPCT &m)
   pg.peering_state.update_pct(m.pg_committed_to);
 }
 
+PGBackend::get_attr_ierrorator::future<ceph::bufferlist>
+ReplicatedBackend::getxattr(
+  const hobject_t& soid,
+  std::string&& key) const
+{
+  return seastar::do_with(key, [this, &soid](auto &key) {
+    return store->get_attr(coll, ghobject_t{soid}, key);
+  });
+}
+
 }
index 7bf067ffc71c01f718ec4300972fc23e8293bd22..a726699ac00499d2ea71e9deb439610be5b23f76 100644 (file)
@@ -34,6 +34,11 @@ public:
   void got_rep_op_reply(const MOSDRepOpReply& reply) final;
   seastar::future<> stop() final;
   void on_actingset_changed(bool same_primary) final;
+
+  PGBackend::get_attr_ierrorator::future<ceph::bufferlist> getxattr(
+    const hobject_t& soid,
+    std::string&& key) const final;
+
 private:
   ll_read_ierrorator::future<ceph::bufferlist>
   _read(const hobject_t& hoid,