}
};
+struct ToSparseReadResult : public Context {
+ bufferlist& data_bl;
+ ceph_le64& len;
+ ToSparseReadResult(bufferlist& bl, ceph_le64& len):
+ data_bl(bl), len(len) {}
+ void finish(int r) {
+ if (r < 0) return;
+ len = r;
+ bufferlist outdata;
+ map<uint64_t, uint64_t> extents = {{0, r}};
+ ::encode(extents, outdata);
+ ::encode_destructively(data_bl, outdata);
+ data_bl.swap(outdata);
+ }
+};
+
template<typename V>
static string list_keys(const map<string, V>& m) {
string s;
/* map extents */
case CEPH_OSD_OP_SPARSE_READ:
tracepoint(osd, do_osd_op_pre_sparse_read, soid.oid.name.c_str(), soid.snap.val, oi.size, oi.truncate_seq, op.extent.offset, op.extent.length, op.extent.truncate_size, op.extent.truncate_seq);
- if (pool.info.require_rollback()) {
- result = -EOPNOTSUPP;
+ if (op.extent.truncate_seq) {
+ dout(0) << "sparse_read does not support truncation sequence " << dendl;
+ result = -EINVAL;
break;
}
++ctx->num_read;
- {
- if (op.extent.truncate_seq) {
- dout(0) << "sparse_read does not support truncation sequence " << dendl;
- result = -EINVAL;
- break;
- }
+ if (pool.info.require_rollback()) {
+ // translate sparse read to a normal one if not supported
+ ctx->pending_async_reads.push_back(
+ make_pair(
+ boost::make_tuple(op.extent.offset, op.extent.length, op.flags),
+ make_pair(&osd_op.outdata, new ToSparseReadResult(osd_op.outdata,
+ op.extent.length))));
+ dout(10) << " async_read (was sparse_read) noted for " << soid << dendl;
+ } else {
// read into a buffer
bufferlist bl;
int total_read = 0;
osd_op.outdata.claim_append(bl);
::encode_destructively(data_bl, osd_op.outdata);
- ctx->delta_stats.num_rd_kb += SHIFT_ROUND_UP(op.extent.length, 10);
- ctx->delta_stats.num_rd++;
-
dout(10) << " sparse_read got " << total_read << " bytes from object " << soid << dendl;
}
+ ctx->delta_stats.num_rd_kb += SHIFT_ROUND_UP(op.extent.length, 10);
+ ctx->delta_stats.num_rd++;
break;
case CEPH_OSD_OP_CALL: