diff options
author | Adam Kupczyk <akupczyk@ibm.com> | 2023-05-10 11:30:23 +0200 |
---|---|---|
committer | Adam Kupczyk <akupczyk@ibm.com> | 2023-07-06 17:28:50 +0200 |
commit | eb854a7148d9183e8b35a3b8f186c8a49ae6ae84 (patch) | |
tree | b41c4c39403aa839e7da0fb758e71ca99d33fe65 /src/os | |
parent | os/bluestore: Add can_merge_blob and merge_blob (diff) | |
download | ceph-eb854a7148d9183e8b35a3b8f186c8a49ae6ae84.tar.xz ceph-eb854a7148d9183e8b35a3b8f186c8a49ae6ae84.zip |
os/bluestore: Add discard_unused_buffers function
When we punch_hole in blobs we leave Buffers unchanged.
Normally it is not a problem, but when we merge blobs there is a collision.
Signed-off-by: Adam Kupczyk <akupczyk@ibm.com>
Diffstat (limited to 'src/os')
-rw-r--r-- | src/os/bluestore/BlueStore.cc | 31 | ||||
-rw-r--r-- | src/os/bluestore/BlueStore.h | 8 |
2 files changed, 37 insertions, 2 deletions
diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index e179c598233..9705df8985e 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -2423,6 +2423,37 @@ bool BlueStore::Blob::can_reuse_blob(uint32_t min_alloc_size, return true; } +#undef dout_prefix +#define dout_prefix *_dout << "bluestore.blob(" << this << ") " +#undef dout_context +#define dout_context cct + +// Cut Buffers that are not covered by extents. +// It happens when we punch hole in Blob, but not refill with new data. +// Normally it is not a problem (other then wasted memory), +// but when 2 Blobs are merged Buffers might collide. +// Todo: in future cut Buffers when we delete extents from Blobs, +// and get rid of this function. +void BlueStore::Blob::discard_unused_buffers(CephContext* cct, BufferCacheShard* cache) +{ + dout(25) << __func__ << " input " << *this << " bc=" << bc << dendl; + const PExtentVector& extents = get_blob().get_extents(); + uint32_t epos = 0; + auto e = extents.begin(); + while(e != extents.end()) { + if (!e->is_valid()) { + bc._discard(cache, epos, e->length); + } + epos += e->length; + ++e; + } + ceph_assert(epos <= blob.get_logical_length()); + // Preferably, we would trim up to blob.get_logical_length(), + // but we copied writing buffers (see _dup_writing) before blob logical_length is fixed. + bc._discard(cache, epos, OBJECT_MAX_SIZE - epos); + dout(25) << __func__ << " output bc=" << bc << dendl; +} + void BlueStore::Blob::dup(const Blob& from, bool copy_used_in_blob) { set_shared_blob(from.shared_blob); diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index 53170d0e07c..c121a426f12 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -401,7 +401,8 @@ public: void _rm_buffer(BufferCacheShard* cache, Buffer *b) { _rm_buffer(cache, buffer_map.find(b->offset)); } - void _rm_buffer(BufferCacheShard* cache, + std::map<uint32_t, std::unique_ptr<Buffer>>::iterator + _rm_buffer(BufferCacheShard* cache, std::map<uint32_t, std::unique_ptr<Buffer>>::iterator p) { ceph_assert(p != buffer_map.end()); cache->_audit("_rm_buffer start"); @@ -410,8 +411,9 @@ public: } else { cache->_rm(p->second.get()); } - buffer_map.erase(p); + p = buffer_map.erase(p); cache->_audit("_rm_buffer end"); + return p; } std::map<uint32_t,std::unique_ptr<Buffer>>::iterator _data_lower_bound( @@ -684,6 +686,8 @@ public: #endif return blob; } + /// clear buffers from unused sections + void discard_unused_buffers(CephContext* cct, BufferCacheShard* cache); inline const BufferSpace& get_bc() const { return bc; |