Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mimic: os/bluestore: backport new bitmap allocator #26983

Merged
merged 21 commits into from Apr 1, 2019
Merged
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
480b285
test/allocator: get rid off bitmap allocator specifics and introduce new
ifed01 May 3, 2018
dd0912f
os/bluestore: add new bitmap allocator
ifed01 May 3, 2018
ba5c402
test/allocator: move bluestore allocator's benchmarks to a standalone UT
ifed01 May 4, 2018
d8d6cdb
os/bluestore: get rid off allocator's reserve method
ifed01 May 7, 2018
4773293
os/bluestore: add release(PExtentVector) helper to Allocator class to
ifed01 May 7, 2018
5525533
os/bluestore: fix improper access to a BitmapFastAllocator::last_pos
ifed01 May 10, 2018
d42bb17
os/bluestore: align BitMap allocator's init_rm_free/init_add_free par…
ifed01 May 11, 2018
5651097
os/bluestore: remove original bitmap allocator
ifed01 May 14, 2018
506dbcc
os/bluestore: more verbose logging in new bitmap allocator
ifed01 May 30, 2018
3885860
os/bluestore: cosmetic cleanup in new bitmap allocator.
ifed01 May 31, 2018
33482e0
os/bluestore: properly respect min_length when analysing partially free
ifed01 May 31, 2018
8b9fb75
os/bluestore: cosmetic new allocator internal method rename.
ifed01 May 31, 2018
ececb8f
os/bluestore: respect min_length as allocation granularity for new
ifed01 May 31, 2018
c645f2f
test/objectstore/unitetest_fastbmap_allocator: replace ASSERT_TRUE with
ifed01 Jun 1, 2018
25b7d0e
os/bluestore: perform allocations aligned with min_length in new bit…
ifed01 Jun 1, 2018
811857a
os/bluestore: rename new bitmap allocator class to BitmapAllocator.
ifed01 Jun 12, 2018
d08e2b7
os/bluestore: provide a rough estimate for bitmap allocator
ifed01 Jun 15, 2018
0bdbe66
os/bluestore: fix overlappedd allocation returned by bitmap allocator
ifed01 Jun 25, 2018
e5de298
os/bluestore: fix minor issues in bitmap logging output
ifed01 Jun 25, 2018
cf984c8
qa/objectstore: bluestore -> bluestore-{bitmap,stupid}
liewegas Nov 30, 2018
f26b219
qa/suites: fix bluestore links
liewegas Dec 5, 2018
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

os/bluestore: get rid off allocator's reserve method

Signed-off-by: Igor Fedotov <ifedotov@suse.com>
(cherry picked from commit 88bea46)
  • Loading branch information...
ifed01 committed May 7, 2018
commit d8d6cdb479649d9830cd517e6d26e3fc4bf7339f
@@ -20,9 +20,6 @@ class Allocator {
public:
virtual ~Allocator() {}

virtual int reserve(uint64_t need) = 0;
virtual void unreserve(uint64_t unused) = 0;

/*
* Allocate required number of blocks in n number of extents.
* Min and Max number of extents are limited by:
@@ -80,35 +80,6 @@ void BitMapAllocator::insert_free(uint64_t off, uint64_t len)
len / m_block_size);
}

int BitMapAllocator::reserve(uint64_t need)
{
int nblks = need / m_block_size; // apply floor
assert(!(need % m_block_size));
dout(10) << __func__ << " instance " << (uint64_t) this
<< " num_used " << m_bit_alloc->get_used_blocks()
<< " total " << m_bit_alloc->total_blocks()
<< dendl;

if (!m_bit_alloc->reserve_blocks(nblks)) {
return -ENOSPC;
}
return 0;
}

void BitMapAllocator::unreserve(uint64_t unused)
{
int nblks = unused / m_block_size;
assert(!(unused % m_block_size));

dout(10) << __func__ << " instance " << (uint64_t) this
<< " unused " << nblks
<< " num used " << m_bit_alloc->get_used_blocks()
<< " total " << m_bit_alloc->total_blocks()
<< dendl;

m_bit_alloc->unreserve_blocks(nblks);
}

int64_t BitMapAllocator::allocate(
uint64_t want_size, uint64_t alloc_unit, uint64_t max_alloc_size,
int64_t hint, PExtentVector *extents)
@@ -119,6 +90,8 @@ int64_t BitMapAllocator::allocate(

assert(!max_alloc_size || max_alloc_size >= alloc_unit);

//FIXME: reproduce reserve/unreserve

dout(10) << __func__ <<" instance "<< (uint64_t) this
<< " want_size " << want_size
<< " alloc_unit " << alloc_unit
@@ -27,9 +27,6 @@ class BitMapAllocator : public Allocator {
BitMapAllocator(CephContext* cct, int64_t device_size, int64_t block_size);
~BitMapAllocator() override;

int reserve(uint64_t need) override;
void unreserve(uint64_t unused) override;

int64_t allocate(
uint64_t want_size, uint64_t alloc_unit, uint64_t max_alloc_size,
int64_t hint, PExtentVector *extents) override;
@@ -215,19 +215,15 @@ int BlueFS::reclaim_blocks(unsigned id, uint64_t want,
<< " want 0x" << std::hex << want << std::dec << dendl;
ceph_assert(id < alloc.size());
ceph_assert(alloc[id]);
int r = alloc[id]->reserve(want);
ceph_assert(r == 0); // caller shouldn't ask for more than they can get

int64_t got = alloc[id]->allocate(want, cct->_conf->bluefs_alloc_size, 0,
extents);
assert(got != 0);
if (got < (int64_t)want) {
alloc[id]->unreserve(want - std::max<int64_t>(0, got));
if (got < 0) {
derr << __func__ << " failed to allocate space to return to bluestore"
<< dendl;
alloc[id]->dump();
return got;
}
if (got < 0) {
derr << __func__ << " failed to allocate space to return to bluestore"
<< dendl;
alloc[id]->dump();
return got;
}

for (auto& p : *extents) {
@@ -236,7 +232,7 @@ int BlueFS::reclaim_blocks(unsigned id, uint64_t want,
}

flush_bdev();
r = _flush_and_sync_log(l);
int r = _flush_and_sync_log(l);
ceph_assert(r == 0);

logger->inc(l_bluefs_reclaim_bytes, got);
@@ -1993,26 +1989,20 @@ int BlueFS::_allocate(uint8_t id, uint64_t len,
uint64_t min_alloc_size = cct->_conf->bluefs_alloc_size;

uint64_t left = round_up_to(len, min_alloc_size);
int r = -ENOSPC;
int64_t alloc_len = 0;
PExtentVector extents;

if (alloc[id]) {
r = alloc[id]->reserve(left);
}

if (r == 0) {
uint64_t hint = 0;
if (!node->extents.empty() && node->extents.back().bdev == id) {
hint = node->extents.back().end();
}
extents.reserve(4); // 4 should be (more than) enough for most allocations
alloc_len = alloc[id]->allocate(left, min_alloc_size, hint, &extents);
}
if (r < 0 || (alloc_len < (int64_t)left)) {
if (r == 0) {
if (alloc_len < (int64_t)left) {
if (alloc_len != 0) {
interval_set<uint64_t> to_release;
alloc[id]->unreserve(left - alloc_len);
for (auto& p : extents) {
to_release.insert(p.offset, p.length);
}
@@ -5366,25 +5366,19 @@ int BlueStore::_balance_bluefs_freespace(PExtentVector *extents)
dout(10) << __func__ << " gifting " << gift
<< " (" << byte_u_t(gift) << ")" << dendl;

// fixme: just do one allocation to start...
int r = alloc->reserve(gift);
assert(r == 0);

int64_t alloc_len = alloc->allocate(gift, cct->_conf->bluefs_alloc_size,
0, 0, extents);

if (alloc_len <= 0) {
dout(0) << __func__ << " no allocate on 0x" << std::hex << gift
<< " min_alloc_size 0x" << min_alloc_size << std::dec << dendl;
alloc->unreserve(gift);
_dump_alloc_on_rebalance_failure();
return 0;
} else if (alloc_len < (int64_t)gift) {
dout(0) << __func__ << " insufficient allocate on 0x" << std::hex << gift
<< " min_alloc_size 0x" << min_alloc_size
<< " allocated 0x" << alloc_len
<< std::dec << dendl;
alloc->unreserve(gift - alloc_len);
_dump_alloc_on_rebalance_failure();
}
for (auto& e : *extents) {
@@ -6628,20 +6622,21 @@ int BlueStore::_fsck(bool deep, bool repair)
if (!e->is_valid()) {
continue;
}
int r = alloc->reserve(e->length);
if (r != 0) {
derr << __func__ << " failed to reserve 0x" << std::hex << e->length
<< " bytes, misreferences repair's incomplete" << std::dec << dendl;
bypass_rest = true;
break;
}
PExtentVector exts;
int64_t alloc_len = alloc->allocate(e->length, min_alloc_size,
0, 0, &exts);
if (alloc_len < (int64_t)e->length) {
derr << __func__ << " allocate failed on 0x" << std::hex << e->length
<< " min_alloc_size 0x" << min_alloc_size << std::dec << dendl;
assert(0 == "allocate failed, wtf");
if (alloc_len > 0) {
interval_set<uint64_t> release_set;
for (auto e : exts) {
release_set.insert(e.offset, e.length);
}
alloc->release(release_set);
}
bypass_rest = true;
break;
}
expected_statfs.allocated += e->length;
if (compressed) {
@@ -6959,8 +6954,6 @@ void BlueStore::inject_leaked(uint64_t len)
txn = db->get_transaction();

PExtentVector exts;
int r = alloc->reserve(len);
assert(r == 0);
int64_t alloc_len = alloc->allocate(len, min_alloc_size,
min_alloc_size * 256, 0, &exts);
ceph_assert(alloc_len >= (int64_t)len);
@@ -10894,19 +10887,19 @@ int BlueStore::_do_alloc_write(
need += wi.blob_length;
}
}
int r = alloc->reserve(need);
if (r < 0) {
derr << __func__ << " failed to reserve 0x" << std::hex << need << std::dec
<< dendl;
return r;
}
PExtentVector prealloc;
prealloc.reserve(2 * wctx->writes.size());;
int prealloc_left = 0;
prealloc_left = alloc->allocate(
need, min_alloc_size, need,
0, &prealloc);
if (prealloc_left < 0) {
derr << __func__ << " failed to allocate 0x" << std::hex << need << std::dec
<< dendl;
return -ENOSPC;
}
ceph_assert(prealloc_left == (int64_t)need);

dout(20) << __func__ << " prealloc " << prealloc << dendl;
auto prealloc_pos = prealloc.begin();

@@ -12,7 +12,6 @@

StupidAllocator::StupidAllocator(CephContext* cct)
: cct(cct), num_free(0),
num_reserved(0),
free(10),
last_alloc(0)
{
@@ -48,28 +47,6 @@ void StupidAllocator::_insert_free(uint64_t off, uint64_t len)
}
}

int StupidAllocator::reserve(uint64_t need)
{
std::lock_guard<std::mutex> l(lock);
ldout(cct, 10) << __func__ << " need 0x" << std::hex << need
<< " num_free 0x" << num_free
<< " num_reserved 0x" << num_reserved << std::dec << dendl;
if ((int64_t)need > num_free - num_reserved)
return -ENOSPC;
num_reserved += need;
return 0;
}

void StupidAllocator::unreserve(uint64_t unused)
{
std::lock_guard<std::mutex> l(lock);
ldout(cct, 10) << __func__ << " unused 0x" << std::hex << unused
<< " num_free 0x" << num_free
<< " num_reserved 0x" << num_reserved << std::dec << dendl;
assert(num_reserved >= (int64_t)unused);
num_reserved -= unused;
}

/// return the effective length of the extent if we align to alloc_unit
uint64_t StupidAllocator::_aligned_len(
StupidAllocator::interval_set_t::iterator p,
@@ -196,9 +173,7 @@ int64_t StupidAllocator::allocate_int(
}

num_free -= *length;
num_reserved -= *length;
ceph_assert(num_free >= 0);
ceph_assert(num_reserved >= 0);
last_alloc = *offset + *length;
return 0;
}
@@ -17,7 +17,6 @@ class StupidAllocator : public Allocator {
std::mutex lock;

int64_t num_free; ///< total bytes in freelist
int64_t num_reserved; ///< reserved bytes

typedef mempool::bluestore_alloc::pool_allocator<
pair<const uint64_t,uint64_t>> allocator_t;
@@ -38,9 +37,6 @@ class StupidAllocator : public Allocator {
StupidAllocator(CephContext* cct);
~StupidAllocator() override;

int reserve(uint64_t need) override;
void unreserve(uint64_t unused) override;

int64_t allocate(
uint64_t want_size, uint64_t alloc_unit, uint64_t max_alloc_size,
int64_t hint, PExtentVector *extents) override;
@@ -57,7 +57,6 @@ TEST_P(AllocTest, test_alloc_min_alloc)
{
init_alloc(blocks, block_size);
alloc->init_add_free(block_size, block_size);
EXPECT_EQ(alloc->reserve(block_size), 0);
PExtentVector extents;
EXPECT_EQ(block_size, alloc->allocate(block_size, block_size,
0, (int64_t) 0, &extents));
@@ -68,7 +67,6 @@ TEST_P(AllocTest, test_alloc_min_alloc)
*/
{
alloc->init_add_free(0, block_size * 4);
EXPECT_EQ(alloc->reserve(block_size * 4), 0);
PExtentVector extents;
EXPECT_EQ(4*block_size,
alloc->allocate(4 * (uint64_t)block_size, (uint64_t) block_size,
@@ -83,7 +81,6 @@ TEST_P(AllocTest, test_alloc_min_alloc)
{
alloc->init_add_free(0, block_size * 2);
alloc->init_add_free(3 * block_size, block_size * 2);
EXPECT_EQ(alloc->reserve(block_size * 4), 0);
PExtentVector extents;

EXPECT_EQ(4*block_size,
@@ -109,7 +106,6 @@ TEST_P(AllocTest, test_alloc_min_max_alloc)
*/
{
alloc->init_add_free(0, block_size * 4);
EXPECT_EQ(alloc->reserve(block_size * 4), 0);
PExtentVector extents;
EXPECT_EQ(4*block_size,
alloc->allocate(4 * (uint64_t)block_size, (uint64_t) block_size,
@@ -127,7 +123,6 @@ TEST_P(AllocTest, test_alloc_min_max_alloc)
*/
{
alloc->init_add_free(0, block_size * 4);
EXPECT_EQ(alloc->reserve(block_size * 4), 0);
PExtentVector extents;
EXPECT_EQ(4*block_size,
alloc->allocate(4 * (uint64_t)block_size, (uint64_t) block_size,
@@ -143,7 +138,6 @@ TEST_P(AllocTest, test_alloc_min_max_alloc)
*/
{
alloc->init_add_free(0, block_size * 1024);
EXPECT_EQ(alloc->reserve(block_size * 1024), 0);
PExtentVector extents;
EXPECT_EQ(1024 * block_size,
alloc->allocate(1024 * (uint64_t)block_size,
@@ -160,7 +154,6 @@ TEST_P(AllocTest, test_alloc_min_max_alloc)
*/
{
alloc->init_add_free(0, block_size * 16);
EXPECT_EQ(alloc->reserve(block_size * 16), 0);
PExtentVector extents;
EXPECT_EQ(16 * block_size,
alloc->allocate(16 * (uint64_t)block_size, (uint64_t) block_size,
@@ -183,7 +176,6 @@ TEST_P(AllocTest, test_alloc_failure)
alloc->init_add_free(0, block_size * 256);
alloc->init_add_free(block_size * 512, block_size * 256);

EXPECT_EQ(alloc->reserve(block_size * 512), 0);
PExtentVector extents;
EXPECT_EQ(512 * block_size,
alloc->allocate(512 * (uint64_t)block_size,
@@ -192,7 +184,6 @@ TEST_P(AllocTest, test_alloc_failure)
alloc->init_add_free(0, block_size * 256);
alloc->init_add_free(block_size * 512, block_size * 256);
extents.clear();
EXPECT_EQ(alloc->reserve(block_size * 512), 0);
EXPECT_EQ(-ENOSPC,
alloc->allocate(512 * (uint64_t)block_size,
(uint64_t) block_size * 512,
@@ -209,7 +200,6 @@ TEST_P(AllocTest, test_alloc_big)
alloc->init_add_free(2*block_size, (blocks-2)*block_size);
for (int64_t big = mas; big < 1048576*128; big*=2) {
cout << big << std::endl;
EXPECT_EQ(alloc->reserve(big), 0);
PExtentVector extents;
EXPECT_EQ(big,
alloc->allocate(big, mas, 0, &extents));
@@ -231,7 +221,6 @@ TEST_P(AllocTest, test_alloc_hint_bmap)
alloc->init_add_free(0, blocks);

PExtentVector extents;
alloc->reserve(blocks);

allocated = alloc->allocate(1, 1, 1, zone_size, &extents);
ASSERT_EQ(1, allocated);
@@ -285,7 +274,6 @@ TEST_P(AllocTest, test_alloc_non_aligned_len)
alloc->init_add_free(2097152, 1064960);
alloc->init_add_free(3670016, 2097152);

EXPECT_EQ(0, alloc->reserve(want_size));
PExtentVector extents;
EXPECT_EQ(want_size, alloc->allocate(want_size, alloc_unit, 0, &extents));
}
@@ -307,12 +295,11 @@ TEST_P(AllocTest, test_alloc_fragmentation)
for (size_t i = 0; i < capacity / alloc_unit; ++i)
{
tmp.clear();
EXPECT_EQ(0, alloc->reserve(want_size));
EXPECT_EQ(want_size, alloc->allocate(want_size, alloc_unit, 0, 0, &tmp));
allocated.insert(allocated.end(), tmp.begin(), tmp.end());
EXPECT_EQ(0.0, alloc->get_fragmentation(alloc_unit));
}
EXPECT_EQ(-ENOSPC, alloc->reserve(want_size));
EXPECT_EQ(-ENOSPC, alloc->allocate(want_size, alloc_unit, 0, 0, &tmp));

for (size_t i = 0; i < allocated.size(); i += 2)
{
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.