void BlueStore::Blob::discard_unallocated(Collection *coll)
{
- if (blob.is_shared()) {
+ if (get_blob().is_shared()) {
return;
}
- if (blob.is_compressed()) {
+ if (get_blob().is_compressed()) {
bool discard = false;
bool all_invalid = true;
- for (auto e : blob.get_extents()) {
+ for (auto e : get_blob().get_extents()) {
if (!e.is_valid()) {
discard = true;
} else {
assert(discard == all_invalid); // in case of compressed blob all
// or none pextents are invalid.
if (discard) {
- shared_blob->bc.discard(shared_blob->get_cache(), 0, blob.get_logical_length());
+ shared_blob->bc.discard(shared_blob->get_cache(), 0,
+ get_blob().get_logical_length());
}
} else {
size_t pos = 0;
- for (auto e : blob.get_extents()) {
+ for (auto e : get_blob().get_extents()) {
if (!e.is_valid()) {
ldout(coll->store->cct, 20) << __func__ << " 0x" << std::hex << pos
<< "~" << e.length
}
pos += e.length;
}
- if (blob.can_prune_tail()) {
- dirty_blob();
- blob.prune_tail();
- used_in_blob.prune_tail(blob.get_ondisk_length());
+ if (get_blob().can_prune_tail()) {
+ dirty_blob().prune_tail();
+ used_in_blob.prune_tail(get_blob().get_ondisk_length());
auto cct = coll->store->cct; //used by dout
- dout(20) << __func__ << " pruned tail, now " << blob << dendl;
+ dout(20) << __func__ << " pruned tail, now " << get_blob() << dendl;
}
}
}
if (used_in_blob.is_empty()) {
uint32_t min_release_size =
- blob.get_release_size(coll->store->min_alloc_size);
- uint64_t l = blob.get_logical_length();
- dout(20) << __func__ << " init 0x" << std::hex << l << ", " << min_release_size
- << std::dec << dendl;
+ get_blob().get_release_size(coll->store->min_alloc_size);
+ uint64_t l = get_blob().get_logical_length();
+ dout(20) << __func__ << " init 0x" << std::hex << l << ", "
+ << min_release_size << std::dec << dendl;
used_in_blob.init(l, min_release_size);
}
used_in_blob.get(
return b.release_extents(empty, logical, r);
}
-bool BlueStore::Blob::try_reuse_blob(uint32_t min_alloc_size,
+bool BlueStore::Blob::can_reuse_blob(uint32_t min_alloc_size,
uint32_t target_blob_size,
uint32_t b_offset,
uint32_t *length0) {
target_blob_size = MAX(blen, target_blob_size);
if (b_offset >= blen) {
- //new data totally stands out of the existing blob
- new_blen = b_offset + length;
+ // new data totally stands out of the existing blob
+ new_blen = end;
} else {
- //new data overlaps with the existing blob
- new_blen = MAX(blen, length + b_offset);
- if (!get_blob().is_unallocated(
- b_offset,
- new_blen > blen ? blen - b_offset : length)) {
- return false;
+ // new data overlaps with the existing blob
+ new_blen = MAX(blen, end);
+
+ uint32_t overlap = 0;
+ if (new_blen > blen) {
+ overlap = blen - b_offset;
+ } else {
+ overlap = length;
+ }
+
+ if (!get_blob().is_unallocated(b_offset, overlap)) {
+ // abort if any piece of the overlap has already been allocated
+ return false;
}
}
+
if (new_blen > blen) {
int64_t overflow = int64_t(new_blen) - target_blob_size;
// Unable to decrease the provided length to fit into max_blob_size
length -= overflow;
*length0 = length;
}
+
if (new_blen > blen) {
dirty_blob().add_tail(new_blen);
used_in_blob.add_tail(new_blen,
- blob.get_release_size(min_alloc_size));
+ get_blob().get_release_size(min_alloc_size));
}
}
return true;
// search suitable extent in both forward and reverse direction in
// [offset - target_max_blob_size, offset + target_max_blob_size] range
- // then check if blob can be reused via try_reuse_blob func or apply
+ // then check if blob can be reused via can_reuse_blob func or apply
// direct/deferred write (the latter for extents including or higher
// than 'offset' only).
do {
logger->inc(l_bluestore_write_small_deferred);
return;
}
- //try to reuse blob
- if (b->try_reuse_blob(min_alloc_size,
+ // try to reuse blob if we can
+ if (b->can_reuse_blob(min_alloc_size,
max_bsize,
offset0 - bstart,
&alloc_len)) {
auto bstart = prev_ep->blob_start();
dout(20) << __func__ << " considering " << *b
<< " bstart 0x" << std::hex << bstart << std::dec << dendl;
- if (b->try_reuse_blob(min_alloc_size,
+ if (b->can_reuse_blob(min_alloc_size,
max_bsize,
offset0 - bstart,
&alloc_len)) {
auto min_off = offset >= max_bsize ? offset - max_bsize : 0;
// search suitable extent in both forward and reverse direction in
// [offset - target_max_blob_size, offset + target_max_blob_size] range
- // then check if blob can be reused via try_reuse_blob func.
+ // then check if blob can be reused via can_reuse_blob func.
bool any_change;
do {
any_change = false;
if (ep != end && ep->logical_offset < offset + max_bsize) {
if (offset >= ep->blob_start() &&
- ep->blob->try_reuse_blob(min_alloc_size, max_bsize,
+ ep->blob->can_reuse_blob(min_alloc_size, max_bsize,
offset - ep->blob_start(),
&l)) {
b = ep->blob;
}
if (prev_ep != end && prev_ep->logical_offset >= min_off) {
- if (prev_ep->blob->try_reuse_blob(min_alloc_size, max_bsize,
+ if (prev_ep->blob->can_reuse_blob(min_alloc_size, max_bsize,
offset - prev_ep->blob_start(),
&l)) {
b = prev_ep->blob;