]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: full-object read crc is mismatch, because truncate modify oi.size and forget...
authorjiawd <jiawendong@xtaotech.com>
Fri, 12 Nov 2021 03:48:56 +0000 (03:48 +0000)
committerNitzan Mordechai <nmordech@redhat.com>
Sun, 19 May 2024 05:03:14 +0000 (05:03 +0000)
when write before truncate, need trim length, if truncate is to 0,
write is [0~128k], write change to [0~0], do nothing, oi.size is 0, x1 = set_data_digest(crc32(-1)).
write is [128k~128k], write change to [128k~0], truncate oi.size to offset 128k, x2 = set_data_digest(crc32(x1)).
write is [256k~128k], write change to [256k~0], truncate oi.size to offset 256k, x3 = set_data_digest(crc32(x2)).
...
write is [4063232~128k], write change to [4063232~0], truncate oi.size to offset 4063232, xn = set_data_digest(crs32(xn-1))
Now, we can see oi.size is 4063232, and data_digest is 0xffffffff, because thelength of in_data of crc is 0 every time.
when read verify crc will reply EIO. (EC pool).

so, when truncate in write, need clear data_digest and DIGEST flag,
when write before truncate, need to trim length, when offset over than oi.size, don't truncate oi.size to offset.

Fixes: https://tracker.ceph.com/issues/53240
Signed-off-by: jiawd <jiawendong@xtaotech.com>
src/osd/PrimaryLogPG.cc

index 62b8aad27d5b9de6fda22e61ae1c9f9a9b891bec..22a4e5a0cf410a42c5c3729c34fd2fd9ffb08a93 100644 (file)
@@ -6746,6 +6746,8 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
               truncate_update_size_and_usage(ctx->delta_stats,
                                              oi,
                                              op.extent.truncate_size);
+             //truncate modify oi.size, need clear old data_digest and DIGEST flag
+             oi.clear_data_digest();
            }
          } else {
            dout(10) << " truncate_seq " << op.extent.truncate_seq << " > current " << seq
@@ -6764,10 +6766,16 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
 
        if (op.extent.length == 0) {
          if (op.extent.offset > oi.size) {
-           t->truncate(
-             soid, op.extent.offset);
-            truncate_update_size_and_usage(ctx->delta_stats, oi,
-                                           op.extent.offset);
+            if (seq && (seq > op.extent.truncate_seq)) {
+              //do nothing
+              //write arrived after truncate, we should not truncate to offset
+            } else {
+             t->truncate(
+               soid, op.extent.offset);
+              truncate_update_size_and_usage(ctx->delta_stats, oi,
+                                             op.extent.offset);
+              oi.clear_data_digest();
+            }
          } else {
            t->nop(soid);
          }