]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librados: add get_inconsistent_objects() API
authorKefu Chai <kchai@redhat.com>
Sat, 30 Jan 2016 07:05:31 +0000 (15:05 +0800)
committerKefu Chai <kchai@redhat.com>
Thu, 25 Feb 2016 04:41:55 +0000 (12:41 +0800)
Fixes: #13505
Signed-off-by: Kefu Chai <kchai@redhat.com>
src/include/rados/librados.hpp
src/librados/IoCtxImpl.cc
src/librados/IoCtxImpl.h
src/librados/librados.cc
src/osdc/Objecter.cc
src/osdc/Objecter.h

index e1593db3cbef0e2f98f3921e6fa521ade35a6b64..765d8cde7821d90612c27c869900780d71ce24aa 100644 (file)
@@ -1204,6 +1204,24 @@ namespace librados
      */
     int get_inconsistent_pgs(int64_t pool_id,
                              std::vector<PlacementGroup>* 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<inconsistent_obj_t>* objects,
+                                 uint32_t* interval);
 
     /// get/wait for the most recent osdmap
     int wait_for_latest_osdmap();
index d78ec2bb08051a26af5a592f2256739da53ebf65..5a984484e923882a167d826e729e9157f5294d67 100644 (file)
@@ -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<inconsistent_obj_t>* 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;
index 2bc554bf654e6be705c05950e11a1fb08f438375..4e0cb0801e5003fffa0fe273bcdb381a3c554679 100644 (file)
@@ -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<inconsistent_obj_t>* 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);
index 31b795dc39044bb19ccdf271659e4019120249a3..5ff38ca4e5604594b6a97828e20f5ca87f48aebb 100644 (file)
@@ -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<inconsistent_obj_t>* 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();
index ddfe42014a81fb0dd4539cb4a9047e3d6ad90401..598c86aad6f636691d3f6872fa2b6c2941e82eee 100644 (file)
@@ -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 <typename T>
+  void do_decode(std::vector<T>& items, std::vector<bufferlist>& 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<inconsistent_obj_t> *objects = nullptr;
+    int *rval;
+
+    C_ObjectOperation_scrub_ls(uint32_t *interval,
+                              std::vector<inconsistent_obj_t> *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 <typename T>
+  void do_scrub_ls(::ObjectOperation *op,
+                  const scrub_ls_arg_t& arg,
+                  std::vector<T> *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<librados::inconsistent_obj_t> *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);
+}
index f6caa991396fbb9cb8598f4d07c081edf36fe0ce..3e8661ee71ba4e1db7214e7859ccea224256d8b0 100644 (file)
@@ -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<librados::inconsistent_obj_t> *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);