From: Kefu Chai Date: Sat, 30 Jan 2016 07:05:31 +0000 (+0800) Subject: librados: add get_inconsistent_objects() API X-Git-Tag: v10.1.0~303^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=dfc2f4823bafdbc45e69c4a35f2e4d4a22d1efdb;p=ceph.git librados: add get_inconsistent_objects() API Fixes: #13505 Signed-off-by: Kefu Chai --- diff --git a/src/include/rados/librados.hpp b/src/include/rados/librados.hpp index e1593db3cbef..765d8cde7821 100644 --- a/src/include/rados/librados.hpp +++ b/src/include/rados/librados.hpp @@ -1204,6 +1204,24 @@ namespace librados */ int get_inconsistent_pgs(int64_t pool_id, std::vector* pgs); + /** + * List the inconsistent objects found in a given PG by last scrub + * + * @param pg the placement group returned by @c pg_list() + * @param start_after the first returned @c objects + * @param max_return the max number of the returned @c objects + * @param c what to do when the operation is complete and safe + * @param objects [out] the objects where inconsistencies are found + * @param interval [in,out] an epoch indicating current interval + * @returns if a non-zero @c interval is specified, will return -EAGAIN i + * the current interval begin epoch is different. + */ + int get_inconsistent_objects(const PlacementGroup& pg, + const object_id_t &start_after, + unsigned max_return, + AioCompletion *c, + std::vector* objects, + uint32_t* interval); /// get/wait for the most recent osdmap int wait_for_latest_osdmap(); diff --git a/src/librados/IoCtxImpl.cc b/src/librados/IoCtxImpl.cc index d78ec2bb0805..5a984484e923 100644 --- a/src/librados/IoCtxImpl.cc +++ b/src/librados/IoCtxImpl.cc @@ -972,6 +972,25 @@ int librados::IoCtxImpl::trunc(const object_t& oid, uint64_t size) return operate(oid, &op, NULL); } +int librados::IoCtxImpl::get_inconsistent_objects(const pg_t& pg, + const librados::object_id_t& start_after, + uint64_t max_to_get, + AioCompletionImpl *c, + std::vector* objects, + uint32_t* interval) +{ + Context *onack = new C_aio_Ack(c); + c->is_read = true; + c->io = this; + + ::ObjectOperation op; + op.scrub_ls(start_after, max_to_get, objects, interval, nullptr); + object_locator_t oloc{poolid, pg.ps()}; + c->tid = objecter->pg_read(oloc.hash, oloc, op, nullptr, CEPH_OSD_FLAG_PGOP, onack, + nullptr, nullptr); + return 0; +} + int librados::IoCtxImpl::tmap_update(const object_t& oid, bufferlist& cmdbl) { ::ObjectOperation wr; diff --git a/src/librados/IoCtxImpl.h b/src/librados/IoCtxImpl.h index 2bc554bf654e..4e0cb0801e50 100644 --- a/src/librados/IoCtxImpl.h +++ b/src/librados/IoCtxImpl.h @@ -206,6 +206,13 @@ struct librados::IoCtxImpl { int hit_set_get(uint32_t hash, AioCompletionImpl *c, time_t stamp, bufferlist *pbl); + int get_inconsistent_objects(const pg_t& pg, + const librados::object_id_t& start_after, + uint64_t max_to_get, + AioCompletionImpl *c, + std::vector* objects, + uint32_t* interval); + void set_sync_op_version(version_t ver); int watch(const object_t& oid, uint64_t *cookie, librados::WatchCtx *ctx, librados::WatchCtx2 *ctx2); diff --git a/src/librados/librados.cc b/src/librados/librados.cc index 31b795dc3904..5ff38ca4e560 100644 --- a/src/librados/librados.cc +++ b/src/librados/librados.cc @@ -2393,6 +2393,28 @@ int librados::Rados::get_inconsistent_pgs(int64_t pool_id, return ::get_inconsistent_pgs(*client, pool_id, pgs); } +int librados::Rados::get_inconsistent_objects(const PlacementGroup& pg, + const object_id_t &start_after, + unsigned max_return, + AioCompletion *c, + std::vector* objects, + uint32_t* interval) +{ + IoCtx ioctx; + const pg_t pgid = pg.impl->pgid; + int r = ioctx_create2(pgid.pool(), ioctx); + if (r < 0) { + return r; + } + + return ioctx.io_ctx_impl->get_inconsistent_objects(pgid, + start_after, + max_return, + c->pc, + objects, + interval); +} + int librados::Rados::wait_for_latest_osdmap() { return client->wait_for_latest_osdmap(); diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc index ddfe42014a81..598c86aad6f6 100644 --- a/src/osdc/Objecter.cc +++ b/src/osdc/Objecter.cc @@ -46,6 +46,7 @@ #include "common/config.h" #include "common/perf_counters.h" +#include "common/scrub_types.h" #include "include/str_list.h" #include "common/errno.h" @@ -5007,3 +5008,77 @@ void Objecter::_enumerate_reply( return; } +namespace { + using namespace librados; + + template + void do_decode(std::vector& items, std::vector& bls) + { + for (auto bl : bls) { + auto p = bl.begin(); + T t; + decode(t, p); + items.push_back(t); + } + } + + struct C_ObjectOperation_scrub_ls : public Context { + bufferlist bl; + uint32_t *interval; + std::vector *objects = nullptr; + int *rval; + + C_ObjectOperation_scrub_ls(uint32_t *interval, + std::vector *objects, + int *rval) + : interval(interval), objects(objects), rval(rval) {} + void finish(int r) override { + if (r < 0 && r != -EAGAIN) + return; + try { + decode(); + } catch (buffer::error&) { + if (rval) + *rval = -EIO; + } + } + private: + void decode() { + scrub_ls_result_t result; + auto p = bl.begin(); + result.decode(p); + *interval = result.interval; + if (objects) { + do_decode(*objects, result.vals); + } + } + }; + + template + void do_scrub_ls(::ObjectOperation *op, + const scrub_ls_arg_t& arg, + std::vector *items, + uint32_t *interval, + int *rval) + { + OSDOp& osd_op = op->add_op(CEPH_OSD_OP_SCRUBLS); + op->flags |= CEPH_OSD_FLAG_PGOP; + assert(interval); + arg.encode(osd_op.indata); + unsigned p = op->ops.size() - 1; + auto *h = new C_ObjectOperation_scrub_ls{interval, items, rval}; + op->out_handler[p] = h; + op->out_bl[p] = &h->bl; + op->out_rval[p] = rval; + } +} + +void ::ObjectOperation::scrub_ls(const librados::object_id_t& start_after, + uint64_t max_to_get, + std::vector *objects, + uint32_t *interval, + int *rval) +{ + scrub_ls_arg_t arg = {*interval, 0, start_after, max_to_get}; + do_scrub_ls(this, arg, objects, interval, rval); +} diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h index f6caa991396f..3e8661ee71ba 100644 --- a/src/osdc/Objecter.h +++ b/src/osdc/Objecter.h @@ -236,6 +236,12 @@ struct ObjectOperation { flags |= CEPH_OSD_FLAG_PGOP; } + void scrub_ls(const librados::object_id_t& start_after, + uint64_t max_to_get, + std::vector *objects, + uint32_t *interval, + int *rval); + void create(bool excl) { OSDOp& o = add_op(CEPH_OSD_OP_CREATE); o.op.flags = (excl ? CEPH_OSD_OP_FLAG_EXCL : 0);