From: Kefu Chai Date: Mon, 13 May 2019 11:08:42 +0000 (+0800) Subject: crimson/osd: add pgnls support X-Git-Tag: v15.1.0~2661^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=bd8f87665cb8d034a3fb5acc368ff534d5b8c424;p=ceph.git crimson/osd: add pgnls support Signed-off-by: Kefu Chai --- diff --git a/src/crimson/os/cyan_store.cc b/src/crimson/os/cyan_store.cc index 4fe9fcb8681..41e4ddfa24c 100644 --- a/src/crimson/os/cyan_store.cc +++ b/src/crimson/os/cyan_store.cc @@ -104,6 +104,31 @@ seastar::future<> CyanStore::mkfs() return seastar::now(); } +seastar::future, 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 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, ghobject_t>( + std::move(objects), next); +} + CyanStore::CollectionRef CyanStore::create_new_collection(const coll_t& cid) { auto c = new Collection{cid}; diff --git a/src/crimson/os/cyan_store.h b/src/crimson/os/cyan_store.h index 455de1092fd..4f34f6b1292 100644 --- a/src/crimson/os/cyan_store.h +++ b/src/crimson/os/cyan_store.h @@ -78,6 +78,11 @@ public: CollectionRef c, const ghobject_t& oid, std::vector&& keys); + seastar::future, 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 list_collections(); diff --git a/src/crimson/osd/pg.cc b/src/crimson/osd/pg.cc index 087ce896f28..c260e3e0fdf 100644 --- a/src/crimson/osd/pg.cc +++ b/src/crimson/osd/pg.cc @@ -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 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(std::move(bl)); + }); +} + seastar::future> PG::do_osd_ops(Ref m) { return seastar::do_with(std::move(m), ceph::os::Transaction{}, diff --git a/src/crimson/osd/pg.h b/src/crimson/osd/pg.h index 2a2d44ce6f6..2e3e7f519f2 100644 --- a/src/crimson/osd/pg.h +++ b/src/crimson/osd/pg.h @@ -134,6 +134,9 @@ private: ObjectState& os, OSDOp& op, ceph::os::Transaction& txn); + seastar::future do_pgnls(ceph::bufferlist& indata, + const std::string& nspace, + uint64_t limit); private: const spg_t pgid; diff --git a/src/crimson/osd/pg_backend.cc b/src/crimson/osd/pg_backend.cc index 9867d87f1ce..639efd4e305 100644 --- a/src/crimson/osd/pg_backend.cc +++ b/src/crimson/osd/pg_backend.cc @@ -1,6 +1,9 @@ #include "pg_backend.h" #include +#include +#include +#include #include #include @@ -271,3 +274,32 @@ seastar::future<> PGBackend::writefull( } return seastar::now(); } + +seastar::future, 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 gobjects, ghobject_t next) { + std::vector 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, hobject_t>( + objects, next.hobj); + }); +} diff --git a/src/crimson/osd/pg_backend.h b/src/crimson/osd/pg_backend.h index 75b5182ab9b..103558e414c 100644 --- a/src/crimson/osd/pg_backend.h +++ b/src/crimson/osd/pg_backend.h @@ -49,6 +49,9 @@ public: cached_os_t&& os, ceph::os::Transaction&& txn, const MOSDOp& m); + seastar::future, hobject_t> list_objects( + const hobject_t& start, + uint64_t limit); protected: const shard_id_t shard;