f(WRITESAME, __CEPH_OSD_OP(WR, DATA, 38), "write-same") \
f(CMPEXT, __CEPH_OSD_OP(RD, DATA, 32), "cmpext") \
\
+ /* Extensible */ \
+ f(SET_REDIRECT, __CEPH_OSD_OP(WR, DATA, 39), "set-redirect") \
+ \
/** attrs **/ \
/* read */ \
f(GETXATTR, __CEPH_OSD_OP(RD, ATTR, 1), "getxattr") \
void cache_pin();
void cache_unpin();
+ /**
+ * Extensible tier
+ *
+ * Set redirect target
+ */
+ void set_redirect(const std::string& tgt_obj, const IoCtx& tgt_ioctx,
+ uint64_t tgt_version);
+
friend class IoCtx;
};
o->cache_evict();
}
+void librados::ObjectWriteOperation::set_redirect(const std::string& tgt_obj,
+ const IoCtx& tgt_ioctx,
+ uint64_t tgt_version)
+{
+ ::ObjectOperation *o = &impl->o;
+ o->set_redirect(object_t(tgt_obj), tgt_ioctx.io_ctx_impl->snap_seq,
+ tgt_ioctx.io_ctx_impl->oloc, tgt_version);
+}
+
void librados::ObjectWriteOperation::tmap_put(const bufferlist &bl)
{
::ObjectOperation *o = &impl->o;
case CEPH_OSD_OP_COPY_FROM: // we handle user_version update explicitly
case CEPH_OSD_OP_CACHE_PIN:
case CEPH_OSD_OP_CACHE_UNPIN:
+ case CEPH_OSD_OP_SET_REDIRECT:
break;
default:
if (op.op & CEPH_OSD_OP_MODE_WR)
}
break;
+ case CEPH_OSD_OP_SET_REDIRECT:
+ ++ctx->num_write;
+ {
+ if (pool.info.is_tier()) {
+ result = -EINVAL;
+ break;
+ }
+ object_t target_name;
+ object_locator_t target_oloc;
+ snapid_t target_snapid = (uint64_t)op.copy_from.snapid;
+ version_t target_version = op.copy_from.src_version;
+ try {
+ ::decode(target_name, bp);
+ ::decode(target_oloc, bp);
+ }
+ catch (buffer::error& e) {
+ result = -EINVAL;
+ goto fail;
+ }
+ pg_t raw_pg;
+ get_osdmap()->object_locator_to_pg(target_name, target_oloc, raw_pg);
+ hobject_t target(target_name, target_oloc.key, target_snapid,
+ raw_pg.ps(), raw_pg.pool(),
+ target_oloc.nspace);
+ if (target == soid) {
+ dout(20) << " set-redirect self is invalid" << dendl;
+ result = -EINVAL;
+ break;
+ }
+ oi.manifest.redirect_target = target;
+ oi.manifest.type = object_manifest_t::TYPE_REDIRECT;
+ t->truncate(soid, 0);
+ if (oi.is_omap() && pool.info.supports_omap()) {
+ t->omap_clear(soid);
+ obs.oi.clear_omap_digest();
+ obs.oi.clear_flag(object_info_t::FLAG_OMAP);
+ }
+ ctx->delta_stats.num_bytes -= oi.size;
+ oi.size = 0;
+ oi.new_object();
+ oi.user_version = target_version;
+ ctx->user_at_version = target_version;
+ /* rm_attrs */
+ map<string,bufferlist> rmattrs;
+ result = getattrs_maybe_cache(ctx->obc,
+ &rmattrs,
+ true);
+ if (result < 0) {
+ return result;
+ }
+ map<string, bufferlist>::iterator iter;
+ for (iter = rmattrs.begin(); iter != rmattrs.end(); ++iter) {
+ const string& name = iter->first;
+ t->rmattr(soid, name);
+ }
+ dout(10) << "set-redirect oid:" << oi.soid << " user_version: " << oi.user_version << dendl;
+ }
+
+ break;
// -- object attrs --
add_op(CEPH_OSD_OP_CACHE_EVICT);
}
+ /*
+ * Extensible tier
+ */
+ void set_redirect(object_t tgt, snapid_t snapid, object_locator_t tgt_oloc,
+ version_t tgt_version) {
+ OSDOp& osd_op = add_op(CEPH_OSD_OP_SET_REDIRECT);
+ osd_op.op.copy_from.snapid = snapid;
+ osd_op.op.copy_from.src_version = tgt_version;
+ ::encode(tgt, osd_op.indata);
+ ::encode(tgt_oloc, osd_op.indata);
+ }
+
void set_alloc_hint(uint64_t expected_object_size,
uint64_t expected_write_size,
uint32_t flags) {
<< cpp_strerror(ret) << std::endl;
goto out;
}
+ } else if (strcmp(nargs[0], "set-redirect") == 0) {
+ if (!pool_name)
+ 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];
+ }
+
+ IoCtx target_ctx;
+ ret = rados.ioctx_create(target, target_ctx);
+ if (target_oloc.size()) {
+ target_ctx.locator_set_key(target_oloc);
+ }
+ if (target_nspace.size()) {
+ target_ctx.set_namespace(target_nspace);
+ }
+
+ ObjectWriteOperation op;
+ op.set_redirect(target_obj, target_ctx, 0);
+ ret = io_ctx.operate(nargs[1], &op);
+ if (ret < 0) {
+ cerr << "error set-redirect " << pool_name << "/" << nargs[1] << " => " << target << "/" << target_obj << ": " << cpp_strerror(ret) << std::endl;
+ goto out;
+ }
} else if (strcmp(nargs[0], "export") == 0) {
// export [filename]
if (!pool_name || nargs.size() > 2) {