*/
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();
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;
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);
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();
#include "common/config.h"
#include "common/perf_counters.h"
+#include "common/scrub_types.h"
#include "include/str_list.h"
#include "common/errno.h"
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);
+}
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);