These greatly complicate the osd implementation and appear unused.
Signed-off-by: Samuel Just <sjust@redhat.com>
#define CEPH_OSD_OP_TYPE_ATTR 0x0300
#define CEPH_OSD_OP_TYPE_EXEC 0x0400
#define CEPH_OSD_OP_TYPE_PG 0x0500
-#define CEPH_OSD_OP_TYPE_MULTI 0x0600 /* multiobject */
+// LEAVE UNUSED 0x0600 used to be multiobject ops
#define __CEPH_OSD_OP1(mode, nr) \
(CEPH_OSD_OP_MODE_##mode | (nr))
/* ESX/SCSI */ \
f(WRITESAME, __CEPH_OSD_OP(WR, DATA, 38), "write-same") \
\
- /** multi **/ \
- f(CLONERANGE, __CEPH_OSD_OP(WR, MULTI, 1), "clonerange") \
- f(ASSERT_SRC_VERSION, __CEPH_OSD_OP(RD, MULTI, 2), "assert-src-version") \
- f(SRC_CMPXATTR, __CEPH_OSD_OP(RD, MULTI, 3), "src-cmpxattr") \
- \
/** attrs **/ \
/* read */ \
f(GETXATTR, __CEPH_OSD_OP(RD, ATTR, 1), "getxattr") \
{
return (op & CEPH_OSD_OP_TYPE) == CEPH_OSD_OP_TYPE_PG;
}
-static inline int ceph_osd_op_type_multi(int op)
-{
- return (op & CEPH_OSD_OP_TYPE) == CEPH_OSD_OP_TYPE_MULTI;
-}
static inline int ceph_osd_op_mode_subop(int op)
{
* operations of the io context - until a different locator key is
* set, all objects in this io context will be placed in the same pg.
*
- * This is useful if you need to do clone_range operations, which must
- * be done with the source and destination objects in the same pg.
- *
* @param io the io context to change
* @param key the key to use as the object locator, or NULL to discard
* any previously set key
const char *buf, size_t data_len,
size_t write_len, uint64_t off);
-/**
- * Efficiently copy a portion of one object to another
- *
- * If the underlying filesystem on the OSD supports it, this will be a
- * copy-on-write clone.
- *
- * The src and dest objects must be in the same pg. To ensure this,
- * the io context should have a locator key set (see
- * rados_ioctx_locator_set_key()).
- *
- * @param io the context in which the data is cloned
- * @param dst the name of the destination object
- * @param dst_off the offset within the destination object (in bytes)
- * @param src the name of the source object
- * @param src_off the offset within the source object (in bytes)
- * @param len how much data to copy
- * @returns 0 on success, negative error code on failure
- */
-CEPH_RADOS_API int rados_clone_range(rados_ioctx_t io, const char *dst,
- uint64_t dst_off, const char *src,
- uint64_t src_off, size_t len);
-
/**
* Append *len* bytes from *buf* into the *oid* object. The value of
* *len* must be <= UINT_MAX/2.
void cmpxattr(const char *name, uint8_t op, const bufferlist& val);
void cmpxattr(const char *name, uint8_t op, uint64_t v);
- void src_cmpxattr(const std::string& src_oid,
- const char *name, int op, const bufferlist& val);
- void src_cmpxattr(const std::string& src_oid,
- const char *name, int op, uint64_t v);
void exec(const char *cls, const char *method, bufferlist& inbl);
void exec(const char *cls, const char *method, bufferlist& inbl, bufferlist *obl, int *prval);
void exec(const char *cls, const char *method, bufferlist& inbl, ObjectOperationCompletion *completion);
void setxattr(const char *name, const bufferlist& bl);
void tmap_update(const bufferlist& cmdbl);
void tmap_put(const bufferlist& bl);
- void clone_range(uint64_t dst_off,
- const std::string& src_oid, uint64_t src_off,
- size_t len);
void selfmanaged_snap_rollback(uint64_t snapid);
/**
int write_full(const std::string& oid, bufferlist& bl);
int writesame(const std::string& oid, bufferlist& bl,
size_t write_len, uint64_t off);
- int clone_range(const std::string& dst_oid, uint64_t dst_off,
- const std::string& src_oid, uint64_t src_off,
- size_t len);
int read(const std::string& oid, bufferlist& bl, size_t len, uint64_t off);
int remove(const std::string& oid);
int remove(const std::string& oid, int flags);
// assert version for next sync operations
void set_assert_version(uint64_t ver);
- void set_assert_src_version(const std::string& o, uint64_t ver);
/**
* Pin/unpin an object in cache tier
assert_ver = 0;
pop = op;
}
- while (!assert_src_version.empty()) {
- map<object_t,uint64_t>::iterator p = assert_src_version.begin();
- op->assert_src_version(p->first, CEPH_NOSNAP, p->second);
- assert_src_version.erase(p);
- pop = op;
- }
return pop;
}
return operate(oid, &op, NULL);
}
-int librados::IoCtxImpl::clone_range(const object_t& dst_oid,
- uint64_t dst_offset,
- const object_t& src_oid,
- uint64_t src_offset,
- uint64_t len)
-{
- ::ObjectOperation wr;
- prepare_assert_ops(&wr);
- wr.clone_range(src_oid, src_offset, len, dst_offset);
- return operate(dst_oid, &wr, NULL);
-}
-
int librados::IoCtxImpl::operate(const object_t& oid, ::ObjectOperation *o,
ceph::real_time *pmtime, int flags)
{
{
assert_ver = ver;
}
-void librados::IoCtxImpl::set_assert_src_version(const object_t& oid,
- uint64_t ver)
-{
- assert_src_version[oid] = ver;
-}
void librados::IoCtxImpl::set_notify_timeout(uint32_t timeout)
{
snapid_t snap_seq;
::SnapContext snapc;
uint64_t assert_ver;
- map<object_t, uint64_t> assert_src_version;
version_t last_objver;
uint32_t notify_timeout;
object_locator_t oloc;
snap_seq = rhs.snap_seq;
snapc = rhs.snapc;
assert_ver = rhs.assert_ver;
- assert_src_version = rhs.assert_src_version;
last_objver = rhs.last_objver;
notify_timeout = rhs.notify_timeout;
oloc = rhs.oloc;
int write_full(const object_t& oid, bufferlist& bl);
int writesame(const object_t& oid, bufferlist& bl,
size_t write_len, uint64_t offset);
- int clone_range(const object_t& dst_oid, uint64_t dst_offset,
- const object_t& src_oid, uint64_t src_offset, uint64_t len);
int read(const object_t& oid, bufferlist& bl, size_t len, uint64_t off);
int mapext(const object_t& oid, uint64_t off, size_t len,
std::map<uint64_t,uint64_t>& m);
version_t last_version();
void set_assert_version(uint64_t ver);
- void set_assert_src_version(const object_t& oid, uint64_t ver);
void set_notify_timeout(uint32_t timeout);
int cache_pin(const object_t& oid);
o->cmpxattr(name, op, CEPH_OSD_CMPXATTR_MODE_U64, bl);
}
-void librados::ObjectOperation::src_cmpxattr(const std::string& src_oid,
- const char *name, int op, const bufferlist& v)
-{
- ::ObjectOperation *o = &impl->o;
- object_t oid(src_oid);
- o->src_cmpxattr(oid, CEPH_NOSNAP, name, v, op, CEPH_OSD_CMPXATTR_MODE_STRING);
-}
-
-void librados::ObjectOperation::src_cmpxattr(const std::string& src_oid,
- const char *name, int op, uint64_t val)
-{
- ::ObjectOperation *o = &impl->o;
- object_t oid(src_oid);
- bufferlist bl;
- ::encode(val, bl);
- o->src_cmpxattr(oid, CEPH_NOSNAP, name, bl, op, CEPH_OSD_CMPXATTR_MODE_U64);
-}
-
void librados::ObjectOperation::assert_version(uint64_t ver)
{
::ObjectOperation *o = &impl->o;
o->tmap_update(c);
}
-void librados::ObjectWriteOperation::clone_range(uint64_t dst_off,
- const std::string& src_oid, uint64_t src_off,
- size_t len)
-{
- ::ObjectOperation *o = &impl->o;
- o->clone_range(src_oid, src_off, len, dst_off);
-}
-
void librados::ObjectWriteOperation::selfmanaged_snap_rollback(snap_t snapid)
{
::ObjectOperation *o = &impl->o;
return io_ctx_impl->writesame(obj, bl, write_len, off);
}
-int librados::IoCtx::clone_range(const std::string& dst_oid, uint64_t dst_off,
- const std::string& src_oid, uint64_t src_off,
- size_t len)
-{
- object_t src(src_oid), dst(dst_oid);
- return io_ctx_impl->clone_range(dst, dst_off, src, src_off, len);
-}
int librados::IoCtx::read(const std::string& oid, bufferlist& bl, size_t len, uint64_t off)
{
io_ctx_impl->set_assert_version(ver);
}
-void librados::IoCtx::set_assert_src_version(const std::string& oid, uint64_t ver)
-{
- object_t obj(oid);
- io_ctx_impl->set_assert_src_version(obj, ver);
-}
-
-int librados::IoCtx::cache_pin(const string& oid)
-{
- object_t obj(oid);
- return io_ctx_impl->cache_pin(obj);
-}
-
-int librados::IoCtx::cache_unpin(const string& oid)
-{
- object_t obj(oid);
- return io_ctx_impl->cache_unpin(obj);
-}
-
void librados::IoCtx::locator_set_key(const string& key)
{
io_ctx_impl->oloc.key = key;
return retval;
}
-extern "C" int rados_clone_range(rados_ioctx_t io, const char *dst, uint64_t dst_off,
- const char *src, uint64_t src_off, size_t len)
-{
- tracepoint(librados, rados_clone_range_enter, io, dst, dst_off, src, src_off, len);
- librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io;
- object_t dst_oid(dst), src_oid(src);
- int retval = ctx->clone_range(dst_oid, dst_off, src_oid, src_off, len);
- tracepoint(librados, rados_clone_range_exit, retval);
- return retval;
-}
-
extern "C" int rados_trunc(rados_ioctx_t io, const char *o, uint64_t size)
{
tracepoint(librados, rados_trunc_enter, io, o, size);
(iter->op.op != CEPH_OSD_OP_GETXATTR) &&
(iter->op.op != CEPH_OSD_OP_GETXATTRS) &&
(iter->op.op != CEPH_OSD_OP_CMPXATTR) &&
- (iter->op.op != CEPH_OSD_OP_SRC_CMPXATTR) &&
(iter->op.op != CEPH_OSD_OP_ASSERT_VER) &&
(iter->op.op != CEPH_OSD_OP_LIST_WATCHERS) &&
(iter->op.op != CEPH_OSD_OP_LIST_SNAPS) &&
- (iter->op.op != CEPH_OSD_OP_ASSERT_SRC_VERSION) &&
(iter->op.op != CEPH_OSD_OP_SETALLOCHINT) &&
(iter->op.op != CEPH_OSD_OP_WRITEFULL) &&
(iter->op.op != CEPH_OSD_OP_ROLLBACK) &&
return e;
}
-// if we have src_oids, we need to be careful of the target being
-// before and a src being after the last_backfill line, or else the
-// operation won't apply properly on the backfill_target. (the
-// opposite is not a problem; if the target is after the line, we
-// don't apply on the backfill_target and it doesn't matter.)
-// With multi-backfill some backfill targets can be ahead of
-// last_backfill_started. We consider each replica individually and
-// take the larger of last_backfill_started and the replicas last_backfill.
-bool PrimaryLogPG::check_src_targ(const hobject_t& soid, const hobject_t& toid) const
-{
- for (set<pg_shard_t>::iterator i = actingbackfill.begin();
- i != actingbackfill.end();
- ++i) {
- if (*i == get_primary()) continue;
- pg_shard_t bt = *i;
- map<pg_shard_t, pg_info_t>::const_iterator iter = peer_info.find(bt);
- assert(iter != peer_info.end());
-
- hobject_t max;
- if (cmp(last_backfill_started, iter->second.last_backfill,
- get_sort_bitwise()) > 0)
- max = last_backfill_started;
- else
- max = iter->second.last_backfill;
-
- if (cmp(toid, max, get_sort_bitwise()) <= 0 &&
- cmp(soid, max, get_sort_bitwise()) > 0)
- return true;
- }
- return false;
-}
-
/** do_op - do an op
* pg lock will be held (if multithreaded)
* osd_lock NOT held.
dout(25) << __func__ << " oi " << obc->obs.oi << dendl;
- // are writes blocked by another object?
- if (obc->blocked_by) {
- dout(10) << "do_op writes for " << obc->obs.oi.soid << " blocked by "
- << obc->blocked_by->obs.oi.soid << dendl;
- wait_for_degraded_object(obc->blocked_by->obs.oi.soid, op);
- return;
- }
-
- // src_oids
- map<hobject_t,ObjectContextRef, hobject_t::BitwiseComparator> src_obc;
for (vector<OSDOp>::iterator p = m->ops.begin(); p != m->ops.end(); ++p) {
OSDOp& osd_op = *p;
osd->reply_op_error(op, -EINVAL);
return;
}
-
- if (!ceph_osd_op_type_multi(osd_op.op.op))
- continue;
- if (osd_op.soid.oid.name.length()) {
- object_locator_t src_oloc;
- get_src_oloc(m->get_oid(), m->get_object_locator(), src_oloc);
- hobject_t src_oid(osd_op.soid, src_oloc.key, m->get_pg().ps(),
- info.pgid.pool(), m->get_object_locator().nspace);
- if (!src_obc.count(src_oid)) {
- ObjectContextRef sobc;
- hobject_t wait_oid;
- int r;
-
- if (src_oid.is_head() && is_missing_object(src_oid)) {
- wait_for_unreadable_object(src_oid, op);
- } else if ((r = find_object_context(
- src_oid, &sobc, false, false,
- &wait_oid)) == -EAGAIN) {
- // missing the specific snap we need; requeue and wait.
- wait_for_unreadable_object(wait_oid, op);
- } else if (r) {
- if (!maybe_handle_cache(op, write_ordered, sobc, r, wait_oid, true))
- osd->reply_op_error(op, r);
- } else if (sobc->obs.oi.is_whiteout()) {
- osd->reply_op_error(op, -ENOENT);
- } else {
- if (sobc->obs.oi.soid.get_key() != obc->obs.oi.soid.get_key() &&
- sobc->obs.oi.soid.get_key() != obc->obs.oi.soid.oid.name &&
- sobc->obs.oi.soid.oid.name != obc->obs.oi.soid.get_key()) {
- dout(1) << " src_oid " << sobc->obs.oi.soid << " != "
- << obc->obs.oi.soid << dendl;
- osd->reply_op_error(op, -EINVAL);
- } else if (is_degraded_or_backfilling_object(sobc->obs.oi.soid) ||
- (check_src_targ(sobc->obs.oi.soid, obc->obs.oi.soid))) {
- if (is_degraded_or_backfilling_object(sobc->obs.oi.soid)) {
- wait_for_degraded_object(sobc->obs.oi.soid, op);
- } else {
- waiting_for_degraded_object[sobc->obs.oi.soid].push_back(op);
- op->mark_delayed("waiting for degraded object");
- }
- dout(10) << " writes for " << obc->obs.oi.soid << " now blocked by "
- << sobc->obs.oi.soid << dendl;
- obc->blocked_by = sobc;
- sobc->blocking.insert(obc);
- } else {
- dout(10) << " src_oid " << src_oid << " obc " << src_obc << dendl;
- src_obc[src_oid] = sobc;
- continue;
- }
- }
- // Error cleanup below
- } else {
- continue;
- }
- // Error cleanup below
- } else {
- dout(10) << "no src oid specified for multi op " << osd_op << dendl;
- osd->reply_op_error(op, -EINVAL);
- }
- return;
}
// any SNAPDIR op needs to have all clones present. treat them as
// src_obc's so that we track references properly and clean up later.
+ map<hobject_t, ObjectContextRef, hobject_t::BitwiseComparator> src_obc;
if (m->get_snapid() == CEPH_SNAPDIR) {
for (vector<snapid_t>::iterator p = obc->ssc->snapset.clones.begin();
p != obc->ssc->snapset.clones.end();
ctx->user_modify = true;
}
- ObjectContextRef src_obc;
- if (ceph_osd_op_type_multi(op.op)) {
- MOSDOp *m = static_cast<MOSDOp *>(ctx->op->get_req());
- object_locator_t src_oloc;
- get_src_oloc(soid.oid, m->get_object_locator(), src_oloc);
- hobject_t src_oid(osd_op.soid, src_oloc.key, soid.get_hash(),
- info.pgid.pool(), src_oloc.nspace);
- src_obc = ctx->src_obc[src_oid];
- dout(10) << " src_oid " << src_oid << " obc " << src_obc << dendl;
- assert(src_obc);
- }
-
// munge -1 truncate to 0 truncate
if (ceph_osd_op_uses_extent(op.op) &&
op.extent.truncate_seq == 1 &&
break;
case CEPH_OSD_OP_CMPXATTR:
- case CEPH_OSD_OP_SRC_CMPXATTR:
++ctx->num_read;
{
string aname;
name[op.xattr.name_len + 1] = 0;
bufferlist xattr;
- if (obs.exists) {
- if (op.op == CEPH_OSD_OP_CMPXATTR)
- result = getattr_maybe_cache(
- ctx->obc,
- name,
- &xattr);
- else
- result = getattr_maybe_cache(
- src_obc,
- name,
- &xattr);
- if (result < 0 && result != -ENODATA)
- break;
-
- ctx->delta_stats.num_rd++;
- ctx->delta_stats.num_rd_kb += SHIFT_ROUND_UP(xattr.length(), 10);
- }
+ result = getattr_maybe_cache(
+ ctx->obc,
+ name,
+ &xattr);
+ if (result < 0 && result != -EEXIST && result != -ENODATA)
+ break;
+
+ ctx->delta_stats.num_rd++;
+ ctx->delta_stats.num_rd_kb += SHIFT_ROUND_UP(xattr.length(), 10);
switch (op.xattr.cmp_mode) {
case CEPH_OSD_CMPXATTR_MODE_STRING:
break;
}
- case CEPH_OSD_OP_ASSERT_SRC_VERSION:
- ++ctx->num_read;
- {
- uint64_t ver = op.assert_ver.ver;
- tracepoint(osd, do_osd_op_pre_assert_src_version, soid.oid.name.c_str(), soid.snap.val, ver);
- if (!ver)
- result = -EINVAL;
- else if (ver < src_obc->obs.oi.user_version)
- result = -ERANGE;
- else if (ver > src_obc->obs.oi.user_version)
- result = -EOVERFLOW;
- break;
- }
-
case CEPH_OSD_OP_NOTIFY:
++ctx->num_read;
{
result = _delete_oid(ctx, ctx->ignore_cache);
break;
- case CEPH_OSD_OP_CLONERANGE:
- tracepoint(osd, do_osd_op_pre_clonerange, soid.oid.name.c_str(), soid.snap.val, op.clonerange.offset, op.clonerange.length, op.clonerange.src_offset);
- if (pool.info.require_rollback()) {
- result = -EOPNOTSUPP;
- break;
- }
- ++ctx->num_read;
- ++ctx->num_write;
- {
- maybe_create_new_object(ctx);
- if (op.clonerange.src_offset + op.clonerange.length > src_obc->obs.oi.size) {
- dout(10) << " clonerange source " << osd_op.soid << " "
- << op.clonerange.src_offset << "~" << op.clonerange.length
- << " extends past size " << src_obc->obs.oi.size << dendl;
- result = -EINVAL;
- break;
- }
- t->clone_range(src_obc->obs.oi.soid,
- obs.oi.soid, op.clonerange.src_offset,
- op.clonerange.length, op.clonerange.offset);
-
- obs.oi.clear_data_digest();
-
- write_update_size_and_usage(ctx->delta_stats, oi, ctx->modified_ranges,
- op.clonerange.offset, op.clonerange.length, false);
- }
- break;
-
case CEPH_OSD_OP_WATCH:
++ctx->num_write;
{
{
dout(10) << "finish_degraded_object " << oid << dendl;
ObjectContextRef obc(object_contexts.lookup(oid));
- if (obc) {
- for (set<ObjectContextRef>::iterator j = obc->blocking.begin();
- j != obc->blocking.end();
- obc->blocking.erase(j++)) {
- dout(10) << " no longer blocking writes for " << (*j)->obs.oi.soid << dendl;
- (*j)->blocked_by = ObjectContextRef();
- }
- }
if (callbacks_for_degraded_object.count(oid)) {
list<Context*> contexts;
contexts.swap(callbacks_for_degraded_object[oid]);
case CEPH_OSD_OP_SCRUBLS:
break;
}
- } else if (ceph_osd_op_type_multi(op.op.op)) {
- switch (op.op.op) {
- case CEPH_OSD_OP_CLONERANGE:
- out << " " << op.op.clonerange.offset << "~" << op.op.clonerange.length
- << " from " << op.soid
- << " offset " << op.op.clonerange.src_offset;
- break;
- case CEPH_OSD_OP_ASSERT_SRC_VERSION:
- out << " v" << op.op.watch.ver
- << " of " << op.soid;
- break;
- case CEPH_OSD_OP_SRC_CMPXATTR:
- out << " " << op.soid;
- if (op.op.xattr.name_len && op.indata.length()) {
- out << " ";
- op.indata.write(0, op.op.xattr.name_len, out);
- }
- if (op.op.xattr.value_len)
- out << " (" << op.op.xattr.value_len << ")";
- out << " op " << (int)op.op.xattr.cmp_op << " mode " << (int)op.op.xattr.cmp_mode;
- break;
- }
}
return out;
}
{
bufferlist::iterator datap = in.begin();
for (unsigned i = 0; i < ops.size(); i++) {
- if (ceph_osd_op_type_multi(ops[i].op.op)) {
- ::decode(ops[i].soid, datap);
- }
if (ops[i].op.payload_len) {
datap.copy(ops[i].op.payload_len, ops[i].indata);
}
void OSDOp::merge_osd_op_vector_in_data(vector<OSDOp>& ops, bufferlist& out)
{
for (unsigned i = 0; i < ops.size(); i++) {
- if (ceph_osd_op_type_multi(ops[i].op.op)) {
- ::encode(ops[i].soid, out);
- }
if (ops[i].indata.length()) {
ops[i].op.payload_len = ops[i].indata.length();
out.append(ops[i].indata);
int unstable_writes, readers, writers_waiting, readers_waiting;
- // set if writes for this object are blocked on another objects recovery
- ObjectContextRef blocked_by; // object blocking our writes
- set<ObjectContextRef> blocking; // objects whose writes we block
-
// any entity in obs.oi.watchers MUST be in either watchers or unconnected_watchers.
map<pair<uint64_t, entity_name_t>, WatchRef> watchers;
case CEPH_OSD_OP_DELETE: code = l_osdc_osdop_delete; break;
case CEPH_OSD_OP_MAPEXT: code = l_osdc_osdop_mapext; break;
case CEPH_OSD_OP_SPARSE_READ: code = l_osdc_osdop_sparse_read; break;
- case CEPH_OSD_OP_CLONERANGE: code = l_osdc_osdop_clonerange; break;
case CEPH_OSD_OP_GETXATTR: code = l_osdc_osdop_getxattr; break;
case CEPH_OSD_OP_SETXATTR: code = l_osdc_osdop_setxattr; break;
case CEPH_OSD_OP_CMPXATTR: code = l_osdc_osdop_cmpxattr; break;
case CEPH_OSD_OP_CALL: code = l_osdc_osdop_call; break;
case CEPH_OSD_OP_WATCH: code = l_osdc_osdop_watch; break;
case CEPH_OSD_OP_NOTIFY: code = l_osdc_osdop_notify; break;
- case CEPH_OSD_OP_SRC_CMPXATTR: code = l_osdc_osdop_src_cmpxattr; break;
}
if (code)
logger->inc(code);
osd_op.op.writesame.data_length = bl.length();
osd_op.indata.claim_append(bl);
}
- void add_clone_range(int op, uint64_t off, uint64_t len,
- const object_t& srcoid, uint64_t srcoff,
- snapid_t srcsnapid) {
- OSDOp& osd_op = add_op(op);
- osd_op.op.clonerange.offset = off;
- osd_op.op.clonerange.length = len;
- osd_op.op.clonerange.src_offset = srcoff;
- osd_op.soid = sobject_t(srcoid, srcsnapid);
- }
void add_xattr(int op, const char *name, const bufferlist& data) {
OSDOp& osd_op = add_op(op);
osd_op.op.xattr.name_len = (name ? strlen(name) : 0);
add_data(CEPH_OSD_OP_SPARSE_READ, off, len, bl);
}
- void clone_range(const object_t& src_oid, uint64_t src_offset, uint64_t len,
- uint64_t dst_offset) {
- add_clone_range(CEPH_OSD_OP_CLONERANGE, dst_offset, len, src_oid,
- src_offset, CEPH_NOSNAP);
- }
-
// object attrs
void getxattr(const char *name, bufferlist *pbl, int *prval) {
bufferlist bl;
OSDOp& osd_op = add_op(CEPH_OSD_OP_ASSERT_VER);
osd_op.op.assert_ver.ver = ver;
}
- void assert_src_version(const object_t& srcoid, snapid_t srcsnapid,
- uint64_t ver) {
- OSDOp& osd_op = add_op(CEPH_OSD_OP_ASSERT_SRC_VERSION);
- osd_op.op.assert_ver.ver = ver;
- ops.rbegin()->soid = sobject_t(srcoid, srcsnapid);
- }
void cmpxattr(const char *name, const bufferlist& val,
int op, int mode) {
o.op.xattr.cmp_op = op;
o.op.xattr.cmp_mode = mode;
}
- void src_cmpxattr(const object_t& srcoid, snapid_t srcsnapid,
- const char *name, const bufferlist& val,
- int op, int mode) {
- add_xattr(CEPH_OSD_OP_SRC_CMPXATTR, name, val);
- OSDOp& o = *ops.rbegin();
- o.soid = sobject_t(srcoid, srcsnapid);
- o.op.xattr.cmp_op = op;
- o.op.xattr.cmp_mode = mode;
- }
void rollback(uint64_t snapid) {
OSDOp& osd_op = add_op(CEPH_OSD_OP_ROLLBACK);
ASSERT_EQ(1024U, size);
}
-TEST_F(LibRadosMiscPP, CloneRangePP) {
- char buf[64];
- memset(buf, 0xcc, sizeof(buf));
- bufferlist bl;
- bl.append(buf, sizeof(buf));
- ASSERT_EQ(0, ioctx.write("foo", bl, sizeof(buf), 0));
- ioctx.locator_set_key("foo");
- ASSERT_EQ(0, ioctx.clone_range("bar", 0, "foo", 0, sizeof(buf)));
- bufferlist bl2;
- ASSERT_EQ(sizeof(buf), (size_t)ioctx.read("bar", bl2, sizeof(buf), 0));
- ASSERT_EQ(0, memcmp(buf, bl2.c_str(), sizeof(buf)));
-}
-
-TEST_F(LibRadosMisc, CloneRange) {
- char buf[128];
- memset(buf, 0xcc, sizeof(buf));
- ASSERT_EQ(0, rados_write(ioctx, "src", buf, sizeof(buf), 0));
- rados_ioctx_locator_set_key(ioctx, "src");
- ASSERT_EQ(0, rados_clone_range(ioctx, "dst", 0, "src", 0, sizeof(buf)));
- char buf2[sizeof(buf)];
- memset(buf2, 0, sizeof(buf2));
- ASSERT_EQ((int)sizeof(buf2), rados_read(ioctx, "dst", buf2, sizeof(buf2), 0));
- ASSERT_EQ(0, memcmp(buf, buf2, sizeof(buf)));
-}
-
TEST_F(LibRadosMiscPP, AssertExistsPP) {
char buf[64];
memset(buf, 0xcc, sizeof(buf));
" create <obj-name> create object\n"
" rm <obj-name> ...[--force-full] [force no matter full or not]remove object(s)\n"
" cp <obj-name> [target-obj] copy object\n"
-" clonedata <src-obj> <dst-obj> clone object data\n"
" listxattr <obj-name>\n"
" getxattr <obj-name> attr\n"
" setxattr <obj-name> attr val\n"
return target_ctx.operate(target_obj, &op);
}
-static int do_clone_data(IoCtx& io_ctx, const char *objname, IoCtx& target_ctx, const char *target_obj)
-{
- string oid(objname);
-
- // get size
- uint64_t size;
- int r = target_ctx.stat(oid, &size, NULL);
- if (r < 0)
- return r;
-
- librados::ObjectWriteOperation write_op;
- string target_oid(target_obj);
-
- /* reset data stream only */
- write_op.create(false);
- write_op.truncate(0);
- write_op.clone_range(0, oid, 0, size);
- return target_ctx.operate(target_oid, &write_op);
-}
-
static int do_copy_pool(Rados& rados, const char *src_pool, const char *target_pool)
{
IoCtx src_ctx, target_ctx;
cerr << "error copying " << pool_name << "/" << nargs[1] << " => " << target << "/" << target_obj << ": " << cpp_strerror(ret) << std::endl;
goto out;
}
- }
- else if (strcmp(nargs[0], "clonedata") == 0) {
- if (!pool_name)
- usage_exit();
-
- if (nargs.size() < 2 || nargs.size() > 3)
- usage_exit();
-
- const char *target = target_pool_name;
- if (!target)
- target = pool_name;
-
- const char *target_obj;
- if (nargs.size() < 3) {
- if (strcmp(target, pool_name) == 0) {
- cerr << "cannot copy object into itself" << std::endl;
- ret = -1;
- goto out;
- }
- target_obj = nargs[1];
- } else {
- target_obj = nargs[2];
- }
-
- // open io context.
- IoCtx target_ctx;
- ret = rados.ioctx_create(target, target_ctx);
- if (ret < 0) {
- cerr << "error opening target pool " << target << ": "
- << cpp_strerror(ret) << std::endl;
- goto out;
- }
- if (oloc.size()) {
- target_ctx.locator_set_key(oloc);
- } else {
- cerr << "must specify locator for clone" << std::endl;
- ret = -1;
- goto out;
- }
- if (nspace.size())
- target_ctx.set_namespace(nspace);
-
- ret = do_clone_data(io_ctx, nargs[1], target_ctx, target_obj);
- if (ret < 0) {
- string src_name = (nspace.size() ? nspace + "/" : "") + nargs[1];
- string target_name = (nspace.size() ? nspace + "/" : "") + target_obj;
- cerr << "error cloning " << pool_name << ">" << src_name << " => " << target << ">" << target_name << ": " << cpp_strerror(ret) << std::endl;
- goto out;
- }
} else if (strcmp(nargs[0], "rm") == 0) {
if (!pool_name || nargs.size() < 2)
usage_exit();
r = io_ctx.read(oid, bl, 0, 1);
assert(r == -EOVERFLOW);
- // test assert_src_version
- r = io_ctx.read(oid, bl, 0, 1);
- assert(r >= 0);
- v = io_ctx.get_last_version();
- cout << oid << " version is " << v << std::endl;
- io_ctx.set_assert_src_version(oid, v);
-
r = io_ctx.exec(oid, "crypto", "sha1", bl, bl2);
cout << "exec returned " << r << std::endl;
const unsigned char *sha1 = (const unsigned char *)bl2.c_str();
assert(r == -ECANCELED);
}
- cout << "src_cmpxattr" << std::endl;
- const char *oidb = "bar-clone";
- {
- ObjectWriteOperation o;
- o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_EQ, val);
- io_ctx.locator_set_key(oid);
- o.write_full(val);
- r = io_ctx.operate(oidb, &o);
- cout << " got " << r << " wanted " << -ECANCELED << " (-ECANCELED)" << std::endl;
- assert(r == -ECANCELED);
- }
- {
- ObjectWriteOperation o;
- o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_NE, val);
- io_ctx.locator_set_key(oid);
- o.write_full(val);
- r = io_ctx.operate(oidb, &o);
- cout << " got " << r << " wanted >= 0" << std::endl;
- assert(r >= 0);
- }
io_ctx.locator_set_key(string());
-
cout << "iterating over objects..." << std::endl;
int num_objs = 0;
for (NObjectIterator iter = io_ctx.nobjects_begin();
)
)
-TRACEPOINT_EVENT(librados, rados_clone_range_enter,
- TP_ARGS(
- rados_ioctx_t, ioctx,
- const char*, dst,
- uint64_t, dst_off,
- const char*, src,
- uint64_t, src_off,
- size_t, len),
- TP_FIELDS(
- ctf_integer_hex(rados_ioctx_t, ioctx, ioctx)
- ctf_string(dst, dst)
- ctf_integer(uint64_t, dst_off, dst_off)
- ctf_string(src, src)
- ctf_integer(uint64_t, src_off, src_off)
- ctf_integer(size_t, len, len)
- )
-)
-
-TRACEPOINT_EVENT(librados, rados_clone_range_exit,
- TP_ARGS(
- int, retval),
- TP_FIELDS(
- ctf_integer(int, retval, retval)
- )
-)
-
TRACEPOINT_EVENT(librados, rados_trunc_enter,
TP_ARGS(
rados_ioctx_t, ioctx,