osd,librados: a rados op to create chunked object

Signed-off-by: Myoungwon Oh <omwmw@sk.com>
This commit is contained in:
myoungwon oh 2017-06-02 16:58:22 +09:00
parent e968c64795
commit bb6f5dc173
7 changed files with 140 additions and 1 deletions

View File

@ -310,6 +310,7 @@ extern int ceph_release_from_features(uint64_t features);
\
/* Extensible */ \
f(SET_REDIRECT, __CEPH_OSD_OP(WR, DATA, 39), "set-redirect") \
f(SET_CHUNK, __CEPH_OSD_OP(WR, DATA, 40), "set-chunk") \
\
/** attrs **/ \
/* read */ \

View File

@ -471,6 +471,9 @@ namespace librados
*/
void set_redirect(const std::string& tgt_obj, const IoCtx& tgt_ioctx,
uint64_t tgt_version);
void set_chunk(uint64_t src_offset, uint64_t src_length, const IoCtx& tgt_ioctx,
std::string tgt_oid, uint64_t tgt_offset);
friend class IoCtx;
};

View File

@ -614,6 +614,17 @@ void librados::ObjectWriteOperation::set_redirect(const std::string& tgt_obj,
tgt_ioctx.io_ctx_impl->oloc, tgt_version);
}
void librados::ObjectWriteOperation::set_chunk(uint64_t src_offset,
uint64_t src_length,
const IoCtx& tgt_ioctx,
string tgt_oid,
uint64_t tgt_offset)
{
::ObjectOperation *o = &impl->o;
o->set_chunk(src_offset, src_length,
tgt_ioctx.io_ctx_impl->oloc, object_t(tgt_oid), tgt_offset);
}
void librados::ObjectWriteOperation::tmap_put(const bufferlist &bl)
{
::ObjectOperation *o = &impl->o;

View File

@ -6105,6 +6105,68 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
break;
case CEPH_OSD_OP_SET_CHUNK:
++ctx->num_write;
{
if (pool.info.is_tier()) {
result = -EINVAL;
break;
}
if (!obs.exists) {
result = -ENOENT;
break;
}
if (get_osdmap()->require_osd_release < CEPH_RELEASE_LUMINOUS) {
result = -EOPNOTSUPP;
break;
}
object_locator_t tgt_oloc;
uint64_t src_offset, src_length, tgt_offset;
object_t tgt_name;
try {
::decode(src_offset, bp);
::decode(src_length, bp);
::decode(tgt_oloc, bp);
::decode(tgt_name, bp);
::decode(tgt_offset, bp);
}
catch (buffer::error& e) {
result = -EINVAL;
goto fail;
}
if (!src_length) {
result = -EINVAL;
goto fail;
}
if (!oi.manifest.is_chunked()) {
oi.manifest.clear();
}
pg_t raw_pg;
chunk_info_t chunk_info;
hobject_t target(tgt_name, tgt_oloc.key, snapid_t(),
raw_pg.ps(), raw_pg.pool(),
tgt_oloc.nspace);
get_osdmap()->object_locator_to_pg(tgt_name, tgt_oloc, raw_pg);
chunk_info.flags = chunk_info_t::FLAG_MISSING;
chunk_info.oid = target;
chunk_info.offset = tgt_offset;
chunk_info.length= src_length;
oi.manifest.chunk_map[src_offset] = chunk_info;
oi.set_flag(object_info_t::FLAG_MANIFEST);
oi.manifest.type = object_manifest_t::TYPE_CHUNKED;
ctx->modify = true;
dout(10) << "set-chunked oid:" << oi.soid << " user_version: " << oi.user_version
<< " chunk_info: " << chunk_info << dendl;
}
break;
// -- object attrs --
case CEPH_OSD_OP_SETXATTR:

View File

@ -4548,7 +4548,7 @@ struct chunk_info_t {
hobject_t oid;
uint32_t flags; // FLAG_*
chunk_info_t() : length(0), flags(0) { }
chunk_info_t() : offset(0), length(0), flags(0) { }
static string get_flag_string(uint64_t flags) {
string r;

View File

@ -1141,6 +1141,16 @@ struct ObjectOperation {
::encode(tgt_oloc, osd_op.indata);
}
void set_chunk(uint64_t src_offset, uint64_t src_length, object_locator_t tgt_oloc,
object_t tgt_oid, uint64_t tgt_offset) {
OSDOp& osd_op = add_op(CEPH_OSD_OP_SET_CHUNK);
::encode(src_offset, osd_op.indata);
::encode(src_length, osd_op.indata);
::encode(tgt_oloc, osd_op.indata);
::encode(tgt_oid, osd_op.indata);
::encode(tgt_offset, osd_op.indata);
}
void set_alloc_hint(uint64_t expected_object_size,
uint64_t expected_write_size,
uint32_t flags) {

View File

@ -122,6 +122,10 @@ void usage(ostream& out)
" listwatchers <obj-name> list the watchers of this object\n"
" set-alloc-hint <obj-name> <expected-object-size> <expected-write-size>\n"
" set allocation hint for an object\n"
" set-redirect <object A> --target-pool <caspool> <target object A>\n"
" set redirect target\n"
" set-chunk <object A> <offset> <length> --target-pool <caspool> <target object A> <taget-offset>\n"
" convert an object to chunked object\n"
"\n"
"IMPORT AND EXPORT\n"
" export [filename]\n"
@ -3486,6 +3490,54 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
cerr << "error set-redirect " << pool_name << "/" << nargs[1] << " => " << target << "/" << target_obj << ": " << cpp_strerror(ret) << std::endl;
goto out;
}
} else if (strcmp(nargs[0], "set-chunk") == 0) {
if (!pool_name)
usage_exit();
const char *target = target_pool_name;
if (!target)
target = pool_name;
uint64_t offset;
uint64_t length;
uint64_t tgt_offset;
string tgt_oid;
if (nargs.size() < 6) {
usage_exit();
} else {
char* endptr = NULL;
offset = strtoull(nargs[2], &endptr, 10);
if (*endptr) {
cerr << "Invalid value for size: '" << nargs[2] << "'" << std::endl;
ret = -EINVAL;
goto out;
}
length = strtoull(nargs[3], &endptr, 10);
if (*endptr) {
cerr << "Invalid value for size: '" << nargs[2] << "'" << std::endl;
ret = -EINVAL;
goto out;
}
tgt_oid = string(nargs[4]);
tgt_offset = strtoull(nargs[5], &endptr, 10);
if (*endptr) {
cerr << "Invalid value for size: '" << nargs[2] << "'" << std::endl;
ret = -EINVAL;
goto out;
}
}
IoCtx target_ctx;
ret = rados.ioctx_create(target, target_ctx);
ObjectWriteOperation op;
op.set_chunk(offset, length, target_ctx, tgt_oid, tgt_offset);
ret = io_ctx.operate(nargs[1], &op);
if (ret < 0) {
cerr << "error set-chunk " << pool_name << "/" << nargs[1] << " " << " offset " << offset
<< " length " << length << " target_pool " << target
<< "tgt_offset: " << tgt_offset << " : " << cpp_strerror(ret) << std::endl;
goto out;
}
} else if (strcmp(nargs[0], "export") == 0) {
// export [filename]
if (!pool_name || nargs.size() > 2) {