Blob* b = b_it->first;
BlobInfo& bi = b_it->second;
if (bi.referenced_bytes == 0) {
- uint64_t len_on_disk = b_it->first->get_blob().get_ondisk_length();
+ uint64_t len_on_disk = b_it->first->get_blob().get_ondisk_capacity();
int64_t blob_expected_for_release =
round_up_to(len_on_disk, min_alloc_size) / min_alloc_size;
void BlueStore::Blob::maybe_prune_tail() {
if (get_blob().can_prune_tail()) {
dirty_blob().prune_tail();
- used_in_blob.prune_tail(get_blob().get_ondisk_length());
+ used_in_blob.prune_tail(get_blob().get_ondisk_capacity());
dout(20) << __func__ << " pruned tail, now " << get_blob() << dendl;
}
}
if (e.blob->get_blob().is_compressed()) {
if (visited_compressed_blobs.insert(e.blob).second) {
e.blob->get_blob().map(
- 0, e.blob->get_blob().get_ondisk_length(),
+ 0, e.blob->get_blob().get_ondisk_size(),
[&](uint64_t offset, uint64_t length) {
frag.note(offset, length);
return 0;
compressed_blob_bls->push_back(bufferlist());
bufferlist& bl = compressed_blob_bls->back();
auto r = bptr->get_blob().map(
- 0, bptr->get_blob().get_ondisk_length(),
+ 0, bptr->get_blob().get_ondisk_size(),
[&](uint64_t offset, uint64_t length) {
int r = bdev->aio_read(offset, length, &bl, ioc);
if (r < 0)
// direct write into unused blocks of an existing mutable blob?
if ((b_off % chunk_size == 0 && b_len % chunk_size == 0) &&
- b->get_blob().get_ondisk_length() >= b_off + b_len &&
+ b->get_blob().get_ondisk_capacity() >= b_off + b_len &&
b->get_blob().is_unused(b_off, b_len) &&
b->get_blob().is_allocated(b_off, b_len)) {
_buffer_cache_write(txc, o, offset, bl,
uint64_t head_read = p2phase(b_off, chunk_size);
uint64_t tail_read = p2nphase(b_off + b_len, chunk_size);
if ((head_read || tail_read) &&
- (b->get_blob().get_ondisk_length() >= b_off + b_len + tail_read) &&
+ (b->get_blob().get_ondisk_capacity() >= b_off + b_len + tail_read) &&
head_read + tail_read < min_alloc_size) {
b_off -= head_read;
b_len += head_read + tail_read;
}
// chunk-aligned deferred overwrite?
- if (b->get_blob().get_ondisk_length() >= b_off + b_len &&
+ if (b->get_blob().get_ondisk_capacity() >= b_off + b_len &&
b_off % chunk_size == 0 &&
b_len % chunk_size == 0 &&
b->get_blob().is_allocated(b_off, b_len)) {
off = offset;
b_off = offset - ep->blob_start();
uint64_t chunk_size = blob.get_chunk_size(block_size);
- uint64_t ondisk = blob.get_ondisk_length();
+ uint64_t ondisk = blob.get_ondisk_capacity();
used = std::min(l, ondisk - b_off);
// will read some data to fill out the chunk?
sb->loaded &&
maybe_unshared_blobs.count(sb)) {
if (b.is_compressed()) {
- expect[sb].get(0, b.get_ondisk_length());
+ expect[sb].get(0, b.get_ondisk_size());
} else {
// todo: it seems to be an overkill to go through map()
b.map(e.blob_offset, e.length, [&](uint64_t off, uint64_t len) {
denc_varint_lowz(logical_length, p);
denc_varint_lowz(compressed_length, p);
} else {
- logical_length = get_ondisk_length();
+ logical_length = get_ondisk_capacity();
}
if (has_csum()) {
denc(csum_type, p);
}
}
- uint32_t get_ondisk_length() const {
+ /// Count blob's capacity for data
+ /// It returns how much data blob can hold without resizing.
+ /// Compressed blobs cannot be modified, so actual disk usage is returned.
+ uint32_t get_ondisk_capacity() const {
uint32_t len = 0;
for (auto &p : extents) {
len += p.length;
return len;
}
+ /// Count blob's usage of disk
+ /// For compressed blobs get_ondisk_capacity == get_ondisk_size.
+ /// It is similar to get_ondisk_capacity() except unmapped extents do not count.
+ uint32_t get_ondisk_size() const {
+ uint32_t len = 0;
+ for (auto &p : extents) {
+ if (p.is_valid()) {
+ len += p.length;
+ }
+ }
+ return len;
+ }
+
uint32_t get_logical_length() const {
return logical_length;
}