OPTION(bluestore_extent_map_shard_max_size, OPT_U32, 1200)
OPTION(bluestore_extent_map_shard_target_size, OPT_U32, 500)
OPTION(bluestore_extent_map_shard_min_size, OPT_U32, 150)
+OPTION(bluestore_extent_map_shard_target_size_slop, OPT_DOUBLE, .2)
OPTION(bluestore_extent_map_inline_shard_prealloc_size, OPT_U32, 256)
OPTION(bluestore_cache_type, OPT_STR, "2q") // lru, 2q
OPTION(bluestore_onode_cache_size, OPT_U32, 16*1024)
}
}
unsigned target = g_conf->bluestore_extent_map_shard_target_size;
+ unsigned slop = target * g_conf->bluestore_extent_map_shard_target_size_slop;
unsigned extent_avg = bytes / extent_map.size();
dout(20) << __func__ << " extent_avg " << extent_avg
- << " target " << target << dendl;
+ << " target " << target << " slop " << slop << dendl;
// reshard
auto ep = extent_map.begin();
unsigned estimate = 0;
unsigned offset = 0;
vector<bluestore_onode_t::shard_info> new_shard_info;
+ unsigned max_blob_end = 0;
while (ep != extent_map.end()) {
dout(30) << " ep " << *ep << dendl;
assert(!ep->blob->is_spanning());
dout(20) << __func__ << " old shard end 0x" << std::hex << shard_end
<< std::dec << dendl;
}
- if (estimate && estimate + extent_avg > target) {
+ // disfavor shard boundaries that span a blob
+ bool would_span = (ep->logical_offset < max_blob_end) || ep->blob_offset;
+ if (estimate &&
+ estimate + extent_avg > target + (would_span ? slop : 0)) {
// new shard
if (offset == 0) {
new_shard_info.emplace_back(bluestore_onode_t::shard_info());
estimate = 0;
}
estimate += extent_avg;
+ uint32_t be = ep->blob_end();
+ if (be > max_blob_end) {
+ max_blob_end = be;
+ }
++ep;
}
o->onode.extent_map_shards.swap(new_shard_info);
return a.logical_offset == b.logical_offset;
}
+ uint32_t blob_end() {
+ return logical_offset + blob->get_blob().get_logical_length() -
+ blob_offset;
+ }
+
bool blob_escapes_range(uint32_t o, uint32_t l) {
uint32_t bstart = logical_offset - blob_offset;
return (bstart < o ||