]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: do not attempt to read past the object size
authorLoic Dachary <loic@dachary.org>
Fri, 28 Feb 2014 12:57:20 +0000 (13:57 +0100)
committerLoic Dachary <loic@dachary.org>
Mon, 3 Mar 2014 08:28:40 +0000 (09:28 +0100)
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 <loic@dachary.org>
src/osd/ReplicatedPG.cc

index 2b64b481b5b1a3b9fed3293ed9cd25db419b0dfe..e537abe006581e74dffa47a3fa5e696d1540d909 100644 (file)
@@ -2915,24 +2915,28 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& 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(