From 47ae8bc56f02598bd9e45ceb9e9695c0dc993c0d Mon Sep 17 00:00:00 2001 From: Adam Kupczyk Date: Tue, 20 May 2025 07:27:26 +0000 Subject: [PATCH] os/bluestore/compression: Fix Estimator::split_and_compress Fixed calculation on effective blob size. When fully non-compressible data is passed, it could cause losing few bytes in the end. Example: -107> 2025-05-17T20:40:50.468+0000 7f267a42f640 15 bluestore(/var/lib/ceph/osd/ceph-4) _do_write_v2_compressed 200000~78002 -> 200000~78002 -106> 2025-05-17T20:40:50.468+0000 7f267a42f640 20 blobs to put: 200000~f000(4d61) 20f000~f000(b51) 21e000~f000(b51) 22d000~f000(b51) 23c000~f000(b51) 24b000~f000(b51) 25a000~f000(b51) 269000~f000(b51) In result we split 0x78002 into 8 * 0xf000, losing 0x2 in the process. Calculations for original: >>> size=0x78002 >>> blobs=(size+0xffff) / 0x10000 >>> blob_size = size / blobs >>> print hex(size), blobs, hex(blob_size) 0x78002 8 0xf000 <-this means roundup is 0xf000 Calculations for fixed: >>> size=0x78002 >>> blobs=(size+0xffff) / 0x10000 >>> blob_size = (size+blobs-1) / blobs >>> print hex(size), blobs, hex(blob_size) 0x78002 8 0xf001 <-this meand roundup is 0x10000 Fixes: https://tracker.ceph.com/issues/71531 Signed-off-by: Adam Kupczyk (cherry picked from commit 80b7d6840ca989d04a86e90ab946b464bd8d5982) --- src/os/bluestore/Compression.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/os/bluestore/Compression.cc b/src/os/bluestore/Compression.cc index 3b4b5f5692f67..45552743d7f56 100644 --- a/src/os/bluestore/Compression.cc +++ b/src/os/bluestore/Compression.cc @@ -188,12 +188,11 @@ int32_t Estimator::split_and_compress( uint32_t size = data_bl.length(); ceph_assert(size > 0); uint32_t blobs = (size + wctx->target_blob_size - 1) / wctx->target_blob_size; - uint32_t blob_size = p2roundup(size / blobs, au_size); - std::vector blob_sizes(blobs); - for (auto& i: blob_sizes) { - i = std::min(size, blob_size); - size -= i; - } + uint32_t blob_size = p2roundup((size + blobs - 1) / blobs, au_size); + // dividing 'size' to 'blobs' + // blobs[*] = blob_size; blobs[last] = whatever remains from 'size' + std::vector blob_sizes(blobs, blob_size); + blob_sizes.back() = size - blob_size * (blobs - 1); int32_t disk_needed = 0; uint32_t bl_src_off = 0; for (auto& i: blob_sizes) { -- 2.39.5