summaryrefslogtreecommitdiffstats
path: root/src/os
diff options
context:
space:
mode:
authorAdam Kupczyk <akupczyk@ibm.com>2023-05-10 11:30:23 +0200
committerAdam Kupczyk <akupczyk@ibm.com>2023-07-06 17:28:50 +0200
commiteb854a7148d9183e8b35a3b8f186c8a49ae6ae84 (patch)
treeb41c4c39403aa839e7da0fb758e71ca99d33fe65 /src/os
parentos/bluestore: Add can_merge_blob and merge_blob (diff)
downloadceph-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.cc31
-rw-r--r--src/os/bluestore/BlueStore.h8
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;