diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 627ee25fdc8dc..32f8071ba82ef 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -1776,11 +1776,18 @@ void BlueStore::ExtentMap::fault_range( { dout(30) << __func__ << " 0x" << std::hex << offset << "~" << length << std::dec << dendl; - auto p = seek_shard(offset); + auto start = seek_shard(offset); auto last = seek_shard(offset + length); + + if (start < 0) + return; + + assert(last >= start); bool first_key = true; string key; - while (p != shards.end()) { + while (start <= last) { + assert((size_t)start < shards.size()); + auto p = &shards[start]; if (!p->loaded) { if (first_key) { get_extent_shard_key(onode->key, p->offset, &key); @@ -1801,10 +1808,7 @@ void BlueStore::ExtentMap::fault_range( assert(p->dirty == false); assert(v.length() == p->shard_info->bytes); } - if (p == last) { - break; - } - ++p; + ++start; } } @@ -1820,12 +1824,18 @@ void BlueStore::ExtentMap::dirty_range( inline_bl.clear(); return; } - auto p = seek_shard(offset); + auto start = seek_shard(offset); auto last = seek_shard(offset + length); - while (p != shards.end()) { + if (start < 0) + return; + + assert(last >= start); + while (start <= last) { + assert((size_t)start < shards.size()); + auto p = &shards[start]; if (!p->loaded) { dout(20) << __func__ << " shard 0x" << std::hex << p->offset << std::dec - << " is not loaded, can't mark dirty" << dendl; + << " is not loaded, can't mark dirty" << dendl; assert(0 == "can't mark unloaded shard dirty"); } if (!p->dirty) { @@ -1833,10 +1843,7 @@ void BlueStore::ExtentMap::dirty_range( << std::dec << " dirty" << dendl; p->dirty = true; } - if (p == last) { - break; - } - ++p; + ++start; } } diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index 362e0316cf9f1..b3da8012cbfd1 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -574,21 +574,28 @@ class BlueStore : public ObjectStore, /// initialize Shards from the onode void init_shards(Onode *on, bool loaded, bool dirty); - /// return shard containing offset - vector::iterator seek_shard(uint32_t offset) { - // fixme: we could do a binary search here - // we want the right-most shard that has an offset <= @offset. - vector::iterator p = shards.begin(); - while (p != shards.end() && - p->offset <= offset) { - ++p; - } - if (p != shards.begin()) { - assert(p == shards.end() || p->offset > offset); - --p; - assert(p->offset <= offset); + /// return index of shard containing offset + /// or -1 if not found + int seek_shard(uint32_t offset) { + size_t end = shards.size(); + size_t mid, left = 0; + size_t right = end; // one passed the right end + + while (left < right) { + mid = left + (right - left) / 2; + if (offset >= shards[mid].offset) { + size_t next = mid + 1; + if (next >= end || offset < shards[next].offset) + return mid; + //continue to search forwards + left = next; + } else { + //continue to search backwards + right = mid; + } } - return p; + + return -1; // not found } /// ensure that a range of the map is loaded