From 0caaa603f6be4a39ae593104a3a3846302696ea0 Mon Sep 17 00:00:00 2001 From: Igor Fedotov Date: Thu, 10 Jan 2019 12:58:05 +0300 Subject: [PATCH] os/bluestore: do not assert on non-zero err codes from compress() call Fixes: https://tracker.ceph.com/issues/37839 Signed-off-by: Igor Fedotov (cherry picked from commit 4083bc29b6b4191a5ef3c17976eeac091626f1b0) --- src/os/bluestore/BlueStore.cc | 73 ++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 6604cee61e5f7..a5c440fc2a1f0 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -10811,36 +10811,57 @@ int BlueStore::_do_alloc_write( // FIXME: memory alignment here is bad bufferlist t; int r = c->compress(wi.bl, t); - ceph_assert(r == 0); - - bluestore_compression_header_t chdr; - chdr.type = c->get_type(); - chdr.length = t.length(); - encode(chdr, wi.compressed_bl); - wi.compressed_bl.claim_append(t); - - wi.compressed_len = wi.compressed_bl.length(); - uint64_t newlen = p2roundup(wi.compressed_len, min_alloc_size); uint64_t want_len_raw = wi.blob_length * crr; uint64_t want_len = p2roundup(want_len_raw, min_alloc_size); - if (newlen <= want_len && newlen < wi.blob_length) { - // Cool. We compressed at least as much as we were hoping to. - // pad out to min_alloc_size - wi.compressed_bl.append_zero(newlen - wi.compressed_len); - logger->inc(l_bluestore_write_pad_bytes, newlen - wi.compressed_len); - dout(20) << __func__ << std::hex << " compressed 0x" << wi.blob_length - << " -> 0x" << wi.compressed_len << " => 0x" << newlen - << " with " << c->get_type() - << std::dec << dendl; - txc->statfs_delta.compressed() += wi.compressed_len; - txc->statfs_delta.compressed_original() += wi.blob_length; - txc->statfs_delta.compressed_allocated() += newlen; - logger->inc(l_bluestore_compress_success_count); - wi.compressed = true; - need += newlen; + bool rejected = false; + uint64_t compressed_len = t.length(); + // do an approximate (fast) estimation for resulting blob size + // that doesn't take header overhead into account + uint64_t result_len = p2roundup(compressed_len, min_alloc_size); + if (r == 0 && result_len <= want_len && result_len < wi.blob_length) { + bluestore_compression_header_t chdr; + chdr.type = c->get_type(); + chdr.length = t.length(); + encode(chdr, wi.compressed_bl); + wi.compressed_bl.claim_append(t); + + compressed_len = wi.compressed_bl.length(); + result_len = p2roundup(compressed_len, min_alloc_size); + if (result_len <= want_len && result_len < wi.blob_length) { + // Cool. We compressed at least as much as we were hoping to. + // pad out to min_alloc_size + wi.compressed_bl.append_zero(result_len - compressed_len); + wi.compressed_len = compressed_len; + wi.compressed = true; + logger->inc(l_bluestore_write_pad_bytes, result_len - compressed_len); + dout(20) << __func__ << std::hex << " compressed 0x" << wi.blob_length + << " -> 0x" << compressed_len << " => 0x" << result_len + << " with " << c->get_type() + << std::dec << dendl; + txc->statfs_delta.compressed() += compressed_len; + txc->statfs_delta.compressed_original() += wi.blob_length; + txc->statfs_delta.compressed_allocated() += result_len; + logger->inc(l_bluestore_compress_success_count); + need += result_len; + } else { + rejected = true; + } + } else if (r != 0) { + dout(5) << __func__ << std::hex << " 0x" << wi.blob_length + << " bytes compressed using " << c->get_type_name() + << std::dec + << " failed with errcode = " << r + << ", leaving uncompressed" + << dendl; + logger->inc(l_bluestore_compress_rejected_count); + need += wi.blob_length; } else { + rejected = true; + } + + if (rejected) { dout(20) << __func__ << std::hex << " 0x" << wi.blob_length - << " compressed to 0x" << wi.compressed_len << " -> 0x" << newlen + << " compressed to 0x" << compressed_len << " -> 0x" << result_len << " with " << c->get_type() << ", which is more than required 0x" << want_len_raw << " -> 0x" << want_len -- 2.39.5