case CEPH_OSD_OP_COPY_GET_CLASSIC:
++ctx->num_read;
- result = fill_in_copy_get(bp, osd_op, ctx->obc, true);
+ result = fill_in_copy_get(ctx, bp, osd_op, ctx->obc, true);
if (result == -EINVAL)
goto fail;
break;
case CEPH_OSD_OP_COPY_GET:
++ctx->num_read;
- result = fill_in_copy_get(bp, osd_op, ctx->obc, false);
+ result = fill_in_copy_get(ctx, bp, osd_op, ctx->obc, false);
if (result == -EINVAL)
goto fail;
break;
}
};
-int ReplicatedPG::fill_in_copy_get(bufferlist::iterator& bp, OSDOp& osd_op,
- ObjectContextRef& obc, bool classic)
+struct C_CopyFrom_AsyncReadCb : public Context {
+ OSDOp *osd_op;
+ object_copy_data_t reply_obj;
+ bool classic;
+ C_CopyFrom_AsyncReadCb(OSDOp *osd_op, bool classic) :
+ osd_op(osd_op), classic(classic) {}
+ void finish(int r) {
+ if (classic) {
+ reply_obj.encode_classic(osd_op->outdata);
+ } else {
+ ::encode(reply_obj, osd_op->outdata);
+ }
+ }
+};
+
+int ReplicatedPG::fill_in_copy_get(
+ OpContext *ctx,
+ bufferlist::iterator& bp,
+ OSDOp& osd_op,
+ ObjectContextRef &obc,
+ bool classic)
{
object_info_t& oi = obc->obs.oi;
hobject_t& soid = oi.soid;
return result;
}
- object_copy_data_t reply_obj;
+ bool async_read_started = false;
+ object_copy_data_t _reply_obj;
+ C_CopyFrom_AsyncReadCb *cb = NULL;
+ if (pool.info.ec_pool()) {
+ cb = new C_CopyFrom_AsyncReadCb(&osd_op, classic);
+ }
+ object_copy_data_t &reply_obj = cb ? cb->reply_obj : _reply_obj;
// size, mtime
reply_obj.size = oi.size;
reply_obj.mtime = oi.mtime;
bufferlist& bl = reply_obj.data;
if (left > 0 && !cursor.data_complete) {
if (cursor.data_offset < oi.size) {
- result = pgbackend->objects_read_sync(
- oi.soid, cursor.data_offset, left, &bl);
- if (result < 0)
- return result;
+ if (cb) {
+ async_read_started = true;
+ ctx->pending_async_reads.push_back(
+ make_pair(
+ make_pair(cursor.data_offset, left),
+ make_pair(&bl, cb)));
+ result = MIN(oi.size - cursor.data_offset, (uint64_t)left);
+ } else {
+ result = pgbackend->objects_read_sync(
+ oi.soid, cursor.data_offset, left, &bl);
+ if (result < 0)
+ return result;
+ }
assert(result <= left);
left -= result;
cursor.data_offset += result;
// omap
std::map<std::string,bufferlist>& out_omap = reply_obj.omap;
- if (left > 0 && !cursor.omap_complete) {
- assert(cursor.data_complete);
- if (cursor.omap_offset.empty()) {
- osd->store->omap_get_header(coll, oi.soid, &reply_obj.omap_header);
- }
- ObjectMap::ObjectMapIterator iter =
- osd->store->get_omap_iterator(coll, oi.soid);
- assert(iter);
- iter->upper_bound(cursor.omap_offset);
- if (iter->valid()) {
- for (; left > 0 && iter->valid(); iter->next()) {
- out_omap.insert(make_pair(iter->key(), iter->value()));
- left -= iter->key().length() + 4 + iter->value().length() + 4;
+ if (pool.info.ec_pool()) {
+ cursor.omap_complete = true;
+ } else {
+ if (left > 0 && !cursor.omap_complete) {
+ assert(cursor.data_complete);
+ if (cursor.omap_offset.empty()) {
+ osd->store->omap_get_header(coll, oi.soid, &reply_obj.omap_header);
+ }
+ ObjectMap::ObjectMapIterator iter =
+ osd->store->get_omap_iterator(coll, oi.soid);
+ assert(iter);
+ iter->upper_bound(cursor.omap_offset);
+ if (iter->valid()) {
+ for (; left > 0 && iter->valid(); iter->next()) {
+ out_omap.insert(make_pair(iter->key(), iter->value()));
+ left -= iter->key().length() + 4 + iter->value().length() + 4;
+ }
+ }
+ if (iter->valid()) {
+ cursor.omap_offset = iter->key();
+ } else {
+ cursor.omap_complete = true;
+ dout(20) << " got omap" << dendl;
}
- }
- if (iter->valid()) {
- cursor.omap_offset = iter->key();
- } else {
- cursor.omap_complete = true;
- dout(20) << " got omap" << dendl;
}
}
<< " " << out_omap.size() << " keys"
<< dendl;
reply_obj.cursor = cursor;
- if (classic) {
- if (reply_obj.omap_header.length() > 0) {
- derr << oi.soid << " omap header being dropped by classic copy-get api"
- << dendl;
+ if (!async_read_started) {
+ if (classic) {
+ reply_obj.encode_classic(osd_op.outdata);
+ } else {
+ ::encode(reply_obj, osd_op.outdata);
}
- reply_obj.encode_classic(osd_op.outdata);
- } else {
- ::encode(reply_obj, osd_op.outdata);
+ }
+ if (cb && !async_read_started) {
+ delete cb;
}
result = 0;
return result;