From: Sage Weil Date: Sun, 18 Mar 2012 16:08:15 +0000 (-0700) Subject: osd: fix object_info.size mismatch file due to truncate_seq on new object X-Git-Tag: v0.44~2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=77c08f866a4aa17cff430cbe4a45a48778ef001c;p=ceph.git osd: fix object_info.size mismatch file due to truncate_seq on new object 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 Reviewed-by: Samuel Just --- diff --git a/src/osd/ReplicatedPG.cc b/src/osd/ReplicatedPG.cc index f87cf99dfa5f8..1b8468029f76b 100644 --- a/src/osd/ReplicatedPG.cc +++ b/src/osd/ReplicatedPG.cc @@ -1945,15 +1945,22 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector& 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;