]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: fix object_info.size mismatch file due to truncate_seq on new object
authorSage Weil <sage.weil@dreamhost.com>
Sun, 18 Mar 2012 16:08:15 +0000 (09:08 -0700)
committerSage Weil <sage.weil@dreamhost.com>
Sun, 18 Mar 2012 16:08:41 +0000 (09:08 -0700)
If the first write that creates an object includes a truncate_seq and
truncate_size, we were taking the truncte patch and doing a truncate op
in our transaction prior to the write, and then setting the object_info
size appropriately.  However, if the object doesn't exist, the truncate
op fails even though the oi.size gets set.

Later, this turns up as a scrub error (see #2080).

Fix this by skipping the truncate if it is a new object.  Instead, we
should just initialize our truncate_{seq,size} metadata so that we're all
up to date for any later writes.

Alternatively, we could touch the object and then truncate it (up) to the
large size, but this is sort of a waste; data beyond a short object eof is
defined to be zeros, so all we would accomplish is making recovery work
harder by copying zeros around.

Fixes: #2080
Signed-off-by: Sage Weil <sage.weil@dreamhost.com>
Reviewed-by: Samuel Just <samuel.just@dreamhost.com>
src/osd/ReplicatedPG.cc

index f87cf99dfa5f8186ebf1bf308e7959f2edf35979..1b8468029f76bae24e0a6dec5d2b1b7919c5858d 100644 (file)
@@ -1945,15 +1945,22 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
         }
        if (op.extent.truncate_seq > seq) {
          // write arrives before trimtrunc
-         dout(10) << " truncate_seq " << op.extent.truncate_seq << " > current " << seq
-                  << ", truncating to " << op.extent.truncate_size << dendl;
-         t.truncate(coll, soid, op.extent.truncate_size);
-         oi.truncate_seq = op.extent.truncate_seq;
-         oi.truncate_size = op.extent.truncate_size;
-         if (op.extent.truncate_size != oi.size) {
-           ctx->delta_stats.num_bytes -= oi.size;
-           ctx->delta_stats.num_bytes += op.extent.truncate_size;
-           oi.size = op.extent.truncate_size;
+         if (obs.exists) {
+           dout(10) << " truncate_seq " << op.extent.truncate_seq << " > current " << seq
+                    << ", truncating to " << op.extent.truncate_size << dendl;
+           t.truncate(coll, soid, op.extent.truncate_size);
+           oi.truncate_seq = op.extent.truncate_seq;
+           oi.truncate_size = op.extent.truncate_size;
+           if (op.extent.truncate_size != oi.size) {
+             ctx->delta_stats.num_bytes -= oi.size;
+             ctx->delta_stats.num_bytes += op.extent.truncate_size;
+             oi.size = op.extent.truncate_size;
+           }
+         } else {
+           dout(10) << " truncate_seq " << op.extent.truncate_seq << " > current " << seq
+                    << ", but object is new" << dendl;
+           oi.truncate_seq = op.extent.truncate_seq;
+           oi.truncate_size = op.extent.truncate_size;
          }
        }
        bufferlist nbl;