]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/osd: add pgnls support
authorKefu Chai <kchai@redhat.com>
Mon, 13 May 2019 11:08:42 +0000 (19:08 +0800)
committerKefu Chai <kchai@redhat.com>
Mon, 13 May 2019 16:02:19 +0000 (00:02 +0800)
Signed-off-by: Kefu Chai <kchai@redhat.com>
src/crimson/os/cyan_store.cc
src/crimson/os/cyan_store.h
src/crimson/osd/pg.cc
src/crimson/osd/pg.h
src/crimson/osd/pg_backend.cc
src/crimson/osd/pg_backend.h

index 4fe9fcb8681d2c2104bcb3187095934493da9e11..41e4ddfa24cadd95bdfd64647ac740fb4bbcf33b 100644 (file)
@@ -104,6 +104,31 @@ seastar::future<> CyanStore::mkfs()
   return seastar::now();
 }
 
+seastar::future<std::vector<ghobject_t>, ghobject_t>
+CyanStore::list_objects(CollectionRef c,
+                        const ghobject_t& start,
+                        const ghobject_t& end,
+                        uint64_t limit)
+{
+  logger().debug("{} {} {} {} {}",
+                 __func__, c->cid, start, end, limit);
+  std::vector<ghobject_t> objects;
+  objects.reserve(limit);
+  ghobject_t next = ghobject_t::get_max();
+  for (const auto& [oid, obj] :
+         boost::make_iterator_range(c->object_map.lower_bound(start),
+                                    c->object_map.end())) {
+    std::ignore = obj;
+    if (oid >= end || objects.size() >= limit) {
+      next = oid;
+      break;
+    }
+    objects.push_back(oid);
+  }
+  return seastar::make_ready_future<std::vector<ghobject_t>, ghobject_t>(
+    std::move(objects), next);
+}
+
 CyanStore::CollectionRef CyanStore::create_new_collection(const coll_t& cid)
 {
   auto c = new Collection{cid};
index 455de1092fddc80c588be89850922f478b1e175c..4f34f6b1292c315d0cb9b62f8873ab3b124927b6 100644 (file)
@@ -78,6 +78,11 @@ public:
     CollectionRef c,
     const ghobject_t& oid,
     std::vector<std::string>&& keys);
+  seastar::future<std::vector<ghobject_t>, ghobject_t> list_objects(
+    CollectionRef c,
+    const ghobject_t& start,
+    const ghobject_t& end,
+    uint64_t limit);
   CollectionRef create_new_collection(const coll_t& cid);
   CollectionRef open_collection(const coll_t& cid);
   std::vector<coll_t> list_collections();
index 087ce896f28745700dd2654ecc64239e300ac21d..c260e3e0fdf59218cd9ff5bb648cd215ba22e9fb 100644 (file)
@@ -42,6 +42,7 @@ namespace {
   }
 }
 
+using ceph::common::local_conf;
 using recovery::AdvMap;
 using recovery::ActMap;
 using recovery::Initialize;
@@ -999,12 +1000,62 @@ PG::do_osd_op(ObjectState& os, OSDOp& osd_op, ceph::os::Transaction& txn)
     return backend->writefull(os, osd_op, txn);
   case CEPH_OSD_OP_SETALLOCHINT:
     return seastar::now();
+  case CEPH_OSD_OP_PGNLS:
+    return do_pgnls(osd_op.indata, os.oi.soid.get_namespace(), op.pgls.count)
+      .then([&osd_op](bufferlist bl) {
+        osd_op.outdata = std::move(bl);
+       return seastar::now();
+    });
   default:
     throw std::runtime_error(
       fmt::format("op '{}' not supported", ceph_osd_op_name(op.op)));
   }
 }
 
+seastar::future<bufferlist> PG::do_pgnls(bufferlist& indata,
+                                         const std::string& nspace,
+                                         uint64_t limit)
+{
+  hobject_t lower_bound;
+  try {
+    ceph::decode(lower_bound, indata);
+  } catch (const buffer::error& e) {
+    throw std::invalid_argument("unable to decode PGNLS handle");
+  }
+  const auto pg_start = pgid.pgid.get_hobj_start();
+  const auto pg_end = pgid.pgid.get_hobj_end(pool.get_pg_num());
+  if (!(lower_bound.is_min() ||
+        lower_bound.is_max() ||
+        (lower_bound >= pg_start && lower_bound < pg_end))) {
+    // this should only happen with a buggy client.
+    throw std::invalid_argument("outside of PG bounds");
+  }
+  return backend->list_objects(lower_bound, limit).then(
+    [lower_bound, pg_end, nspace](auto objects, auto next) {
+      auto in_my_namespace = [&nspace](const hobject_t& o) {
+        if (o.get_namespace() == local_conf()->osd_hit_set_namespace) {
+          return false;
+        } else if (nspace == librados::all_nspaces) {
+          return true;
+        } else {
+          return o.get_namespace() == nspace;
+        }
+      };
+      pg_nls_response_t response;
+      boost::copy(objects |
+        boost::adaptors::filtered(in_my_namespace) |
+        boost::adaptors::transformed([](const hobject_t& o) {
+          return librados::ListObjectImpl{o.get_namespace(),
+                                          o.oid.name,
+                                          o.get_key()}; }),
+        std::back_inserter(response.entries));
+      response.handle = next.is_max() ? pg_end : next;
+      bufferlist bl;
+      encode(response, bl);
+      return seastar::make_ready_future<bufferlist>(std::move(bl));
+  });
+}
+
 seastar::future<Ref<MOSDOpReply>> PG::do_osd_ops(Ref<MOSDOp> m)
 {
   return seastar::do_with(std::move(m), ceph::os::Transaction{},
index 2a2d44ce6f64dea5efdd2fb0589371f5e4b80046..2e3e7f519f231b2fc08f5ddc7a35b584f3e74485 100644 (file)
@@ -134,6 +134,9 @@ private:
     ObjectState& os,
     OSDOp& op,
     ceph::os::Transaction& txn);
+  seastar::future<ceph::bufferlist> do_pgnls(ceph::bufferlist& indata,
+                                            const std::string& nspace,
+                                            uint64_t limit);
 
 private:
   const spg_t pgid;
index 9867d87f1cea398588282d304a1361f43595ae52..639efd4e30526a8bc86e200b6b7bb6fa093ccf21 100644 (file)
@@ -1,6 +1,9 @@
 #include "pg_backend.h"
 
 #include <optional>
+#include <boost/range/adaptor/filtered.hpp>
+#include <boost/range/adaptor/transformed.hpp>
+#include <boost/range/algorithm/copy.hpp>
 #include <fmt/ostream.h>
 #include <seastar/core/print.hh>
 
@@ -271,3 +274,32 @@ seastar::future<> PGBackend::writefull(
   }
   return seastar::now();
 }
+
+seastar::future<std::vector<hobject_t>, hobject_t>
+PGBackend::list_objects(const hobject_t& start, uint64_t limit)
+{
+  auto gstart = start.is_min() ? ghobject_t{} : ghobject_t{start, 0, shard};
+  return store->list_objects(coll,
+                             gstart,
+                             ghobject_t::get_max(),
+                             limit)
+    .then([this](std::vector<ghobject_t> gobjects, ghobject_t next) {
+      std::vector<hobject_t> objects;
+      boost::copy(gobjects |
+        boost::adaptors::filtered([](const ghobject_t& o) {
+          if (o.is_pgmeta()) {
+            return false;
+          } else if (o.hobj.is_temp()) {
+            return false;
+          } else {
+            return o.is_no_gen();
+          }
+        }) |
+        boost::adaptors::transformed([](const ghobject_t& o) {
+          return o.hobj;
+        }),
+        std::back_inserter(objects));
+      return seastar::make_ready_future<std::vector<hobject_t>, hobject_t>(
+        objects, next.hobj);
+    });
+}
index 75b5182ab9bb338479b3ae83d1dc5ac430f7f68b..103558e414cbce1850750b759a58b39e335c0e00 100644 (file)
@@ -49,6 +49,9 @@ public:
     cached_os_t&& os,
     ceph::os::Transaction&& txn,
     const MOSDOp& m);
+  seastar::future<std::vector<hobject_t>, hobject_t> list_objects(
+    const hobject_t& start,
+    uint64_t limit);
 
 protected:
   const shard_id_t shard;