Project

General

Profile

Bug #56424 » a.diff

patch for v15.2.16 to fix blob's AUs accounting - Igor Fedotov, 06/30/2022 07:40 PM

View differences:

src/os/bluestore/bluestore_types.cc
bluestore_blob_use_tracker_t::bluestore_blob_use_tracker_t(
const bluestore_blob_use_tracker_t& tracker)
: au_size{tracker.au_size},
num_au{tracker.num_au},
num_au(0),
alloc_au(0),
bytes_per_au{nullptr}
{
if (num_au > 0) {
allocate();
if (tracker.num_au > 0) {
allocate(tracker.num_au);
std::copy(tracker.bytes_per_au, tracker.bytes_per_au + num_au, bytes_per_au);
} else {
total_bytes = tracker.total_bytes;
......
}
clear();
au_size = rhs.au_size;
num_au = rhs.num_au;
if (rhs.num_au > 0) {
allocate();
allocate( rhs.num_au);
std::copy(rhs.bytes_per_au, rhs.bytes_per_au + num_au, bytes_per_au);
} else {
total_bytes = rhs.total_bytes;
......
return *this;
}
void bluestore_blob_use_tracker_t::allocate()
void bluestore_blob_use_tracker_t::allocate(uint32_t au_count)
{
ceph_assert(num_au != 0);
bytes_per_au = new uint32_t[num_au];
ceph_assert(au_count != 0);
ceph_assert(num_au == 0);
ceph_assert(alloc_au == 0);
num_au = alloc_au = au_count;
bytes_per_au = new uint32_t[alloc_au];
mempool::get_pool(
mempool::pool_index_t(mempool::mempool_bluestore_cache_other)).
adjust_count(1, sizeof(uint32_t) * num_au);
adjust_count(alloc_au, sizeof(uint32_t) * alloc_au);
for (uint32_t i = 0; i < num_au; ++i) {
bytes_per_au[i] = 0;
}
}
void bluestore_blob_use_tracker_t::release(uint32_t au_count, uint32_t* ptr) {
if (au_count) {
delete[] ptr;
mempool::get_pool(
mempool::pool_index_t(mempool::mempool_bluestore_cache_other)).
adjust_count(-au_count, -sizeof(uint32_t) * au_count);
}
}
void bluestore_blob_use_tracker_t::init(
uint32_t full_length, uint32_t _au_size) {
ceph_assert(!au_size || is_empty());
......
uint32_t _num_au = round_up_to(full_length, _au_size) / _au_size;
au_size = _au_size;
if ( _num_au > 1 ) {
num_au = _num_au;
allocate();
allocate(_num_au);
}
}
src/os/bluestore/bluestore_types.h
// 1) Struct isn't packed hence it's padded. And even if it's packed see 2)
// 2) Mem manager has its own granularity, most probably >= 8 bytes
//
uint32_t au_size; // Allocation (=tracking) unit size,
// == 0 if uninitialized
uint32_t num_au; // Amount of allocation units tracked
// == 0 if single unit or the whole blob is tracked
uint32_t au_size; // Allocation (=tracking) unit size,
// == 0 if uninitialized
uint32_t num_au; // Amount of allocation units tracked
// == 0 if single unit or the whole blob is tracked
uint32_t alloc_au; // Amount of allocation units allocated
union {
uint32_t* bytes_per_au;
......
};
bluestore_blob_use_tracker_t()
: au_size(0), num_au(0), bytes_per_au(nullptr) {
: au_size(0), num_au(0), alloc_au(0), bytes_per_au(nullptr) {
}
bluestore_blob_use_tracker_t(const bluestore_blob_use_tracker_t& tracker);
bluestore_blob_use_tracker_t& operator=(const bluestore_blob_use_tracker_t& rhs);
......
}
void clear() {
if (num_au != 0) {
delete[] bytes_per_au;
mempool::get_pool(
mempool::pool_index_t(mempool::mempool_bluestore_cache_other)).
adjust_count(-1, -sizeof(uint32_t) * num_au);
}
release(alloc_au, bytes_per_au);
num_au = 0;
alloc_au = 0;
bytes_per_au = 0;
au_size = 0;
num_au = 0;
}
uint32_t get_referenced_bytes() const {
......
ceph_assert(_num_au <= num_au);
if (_num_au) {
num_au = _num_au; // bytes_per_au array is left unmodified
} else {
clear();
}
......
if (_num_au > num_au) {
auto old_bytes = bytes_per_au;
auto old_num_au = num_au;
num_au = _num_au;
allocate();
auto old_alloc_au = alloc_au;
alloc_au = num_au = 0; // to bypass an assertion in allocate()
bytes_per_au = nullptr;
allocate(_num_au);
for (size_t i = 0; i < old_num_au; i++) {
bytes_per_au[i] = old_bytes[i];
}
for (size_t i = old_num_au; i < num_au; i++) {
bytes_per_au[i] = 0;
}
delete[] old_bytes;
release(old_alloc_au, old_bytes);
}
}
}
......
clear();
denc_varint(au_size, p);
if (au_size) {
denc_varint(num_au, p);
if (!num_au) {
uint32_t _num_au;
denc_varint(_num_au, p);
if (!_num_au) {
num_au = 0;
denc_varint(total_bytes, p);
} else {
allocate();
for (size_t i = 0; i < num_au; ++i) {
allocate(_num_au);
for (size_t i = 0; i < _num_au; ++i) {
denc_varint(bytes_per_au[i], p);
}
}
......
void dump(Formatter *f) const;
static void generate_test_instances(list<bluestore_blob_use_tracker_t*>& o);
private:
void allocate();
void allocate(uint32_t _num_au);
void release(uint32_t _num_au, uint32_t* ptr);
};
WRITE_CLASS_DENC(bluestore_blob_use_tracker_t)
ostream& operator<<(ostream& out, const bluestore_blob_use_tracker_t& rm);
(9-9/12)