From: Loic Dachary Date: Fri, 28 Feb 2014 12:57:20 +0000 (+0100) Subject: osd: do not attempt to read past the object size X-Git-Tag: v0.78~105^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=927153f5c7ffd8d5f0a4a9a770f68aa9d2021c9f;p=ceph.git osd: do not attempt to read past the object size When reading from a replicated pool, trying to read more than the object size results in a short read that does not go beyond the object size. In erasure coded pools, objects are padded and the read will return more bytes than the object actually contains. http://tracker.ceph.com/issues/7423 fixes #7423 Signed-off-by: Loic Dachary --- diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc index 2b64b481b5b1..e537abe00658 100644 --- a/src/osd/ReplicatedPG.cc +++ b/src/osd/ReplicatedPG.cc @@ -2915,24 +2915,28 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector& ops) case CEPH_OSD_OP_READ: ++ctx->num_read; { - uint64_t trim = (uint64_t)-1; __u32 seq = oi.truncate_seq; + uint64_t size = oi.size; + bool trimmed_read = false; // are we beyond truncate_size? if ( (seq < op.extent.truncate_seq) && - (op.extent.offset + op.extent.length > op.extent.truncate_size) ) { - - // truncated portion of the read - uint64_t from = MAX(op.extent.offset, op.extent.truncate_size); // also end of data - uint64_t to = op.extent.offset + op.extent.length; - trim = to - from; - - op.extent.length = op.extent.length - trim; + (op.extent.offset + op.extent.length > op.extent.truncate_size) ) + size = op.extent.truncate_size; + + if (op.extent.offset >= size) { + op.extent.length = 0; + trimmed_read = true; + } else if (op.extent.offset + op.extent.length > size) { + op.extent.length = size - op.extent.offset; + trimmed_read = true; } // read into a buffer bufferlist bl; - if (trim != (uint64_t)-1 && op.extent.length == 0) { - // read size was trimmed to zero + if (trimmed_read && op.extent.length == 0) { + // read size was trimmed to zero and it is expected to do nothing + // a read operation of 0 bytes does *not* do nothing, this is why + // the trimmed_read boolean is needed } else if (pool.info.require_rollback()) { ctx->pending_async_reads.push_back( make_pair(