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

os/bluestore/BlueFS: use StupidAllocator; fix async compaction bug #11087

Merged
merged 4 commits into from Sep 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/common/config_opts.h
Expand Up @@ -934,6 +934,7 @@ OPTION(bluefs_log_compact_min_size, OPT_U64, 16*1048576) // before we consider
OPTION(bluefs_min_flush_size, OPT_U64, 65536) // ignore flush until its this big
OPTION(bluefs_compact_log_sync, OPT_BOOL, false) // sync or async log compaction?
OPTION(bluefs_buffered_io, OPT_BOOL, false)
OPTION(bluefs_allocator, OPT_STR, "stupid") // stupid | bitmap

OPTION(bluestore_bluefs, OPT_BOOL, true)
OPTION(bluestore_bluefs_env_mirror, OPT_BOOL, false) // mirror to normal Env for debug
Expand Down
18 changes: 13 additions & 5 deletions src/os/bluestore/BlueFS.cc
Expand Up @@ -314,7 +314,7 @@ void BlueFS::_init_alloc()
continue;
}
assert(bdev[id]->get_size());
alloc[id] = Allocator::create(g_conf->bluestore_allocator,
alloc[id] = Allocator::create(g_conf->bluefs_allocator,
bdev[id]->get_size(),
g_conf->bluefs_alloc_size);
interval_set<uint64_t>& p = block_all[id];
Expand Down Expand Up @@ -1029,6 +1029,7 @@ void BlueFS::_compact_log_dump_metadata(bluefs_transaction_t *t)
if (p.first == 1)
continue;
dout(20) << __func__ << " op_file_update " << p.second->fnode << dendl;
assert(p.first > 1);
t->op_file_update(p.second->fnode);
}
for (auto& p : dir_map) {
Expand Down Expand Up @@ -1418,15 +1419,16 @@ int BlueFS::_flush_range(FileWriter *h, uint64_t offset, uint64_t length)
}
if (h->file->fnode.size < offset + length) {
h->file->fnode.size = offset + length;
if (h->file->fnode.ino != 1) {
// we do not need to dirty the log file when the file size
// changes because replay is smart enough to discover it on its
// own.
if (h->file->fnode.ino > 1) {
// we do not need to dirty the log file (or it's compacting
// replacement) when the file size changes because replay is
// smart enough to discover it on its own.
must_dirty = true;
}
}
if (must_dirty) {
h->file->fnode.mtime = ceph_clock_now(NULL);
assert(h->file->fnode.ino >= 1);
log_t.op_file_update(h->file->fnode);
if (h->file->dirty_seq == 0) {
h->file->dirty_seq = log_seq + 1;
Expand Down Expand Up @@ -1581,6 +1583,10 @@ int BlueFS::_truncate(FileWriter *h, uint64_t offset)
dout(10) << __func__ << " deleted, no-op" << dendl;
return 0;
}

// we never truncate internal log files
assert(h->file->fnode.ino > 1);

// truncate off unflushed data?
if (h->pos < offset &&
h->pos + h->buffer.length() > offset) {
Expand Down Expand Up @@ -1708,6 +1714,7 @@ int BlueFS::_preallocate(FileRef f, uint64_t off, uint64_t len)
dout(10) << __func__ << " deleted, no-op" << dendl;
return 0;
}
assert(f->fnode.ino > 1);
uint64_t allocated = f->fnode.get_allocated();
if (off + len > allocated) {
uint64_t want = off + len - allocated;
Expand Down Expand Up @@ -1806,6 +1813,7 @@ int BlueFS::open_for_write(
file->fnode.extents.clear();
}
}
assert(file->fnode.ino > 1);

file->fnode.mtime = ceph_clock_now(NULL);
file->fnode.prefer_bdev = BlueFS::BDEV_DB;
Expand Down
64 changes: 38 additions & 26 deletions src/os/bluestore/StupidAllocator.cc
Expand Up @@ -27,21 +27,23 @@ unsigned StupidAllocator::_choose_bin(uint64_t orig_len)
{
uint64_t len = orig_len / g_conf->bdev_block_size;
int bin = std::min((int)cbits(len), (int)free.size() - 1);
dout(30) << __func__ << " len " << orig_len << " -> " << bin << dendl;
dout(30) << __func__ << " len 0x" << std::hex << orig_len << std::dec
<< " -> " << bin << dendl;
return bin;
}

void StupidAllocator::_insert_free(uint64_t off, uint64_t len)
{
unsigned bin = _choose_bin(len);
dout(30) << __func__ << " " << off << "~" << len << " in bin " << bin << dendl;
dout(30) << __func__ << " 0x" << std::hex << off << "~" << len << std::dec
<< " in bin " << bin << dendl;
while (true) {
free[bin].insert(off, len, &off, &len);
unsigned newbin = _choose_bin(len);
if (newbin == bin)
break;
dout(30) << __func__ << " promoting " << off << "~" << len
<< " to bin " << newbin << dendl;
dout(30) << __func__ << " promoting 0x" << std::hex << off << "~" << len
<< std::dec << " to bin " << newbin << dendl;
free[bin].erase(off, len);
bin = newbin;
}
Expand All @@ -50,8 +52,9 @@ void StupidAllocator::_insert_free(uint64_t off, uint64_t len)
int StupidAllocator::reserve(uint64_t need)
{
std::lock_guard<std::mutex> l(lock);
dout(10) << __func__ << " need " << need << " num_free " << num_free
<< " num_reserved " << num_reserved << dendl;
dout(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;
Expand All @@ -61,8 +64,9 @@ int StupidAllocator::reserve(uint64_t need)
void StupidAllocator::unreserve(uint64_t unused)
{
std::lock_guard<std::mutex> l(lock);
dout(10) << __func__ << " unused " << unused << " num_free " << num_free
<< " num_reserved " << num_reserved << dendl;
dout(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;
}
Expand All @@ -85,9 +89,9 @@ int StupidAllocator::allocate(
uint64_t *offset, uint32_t *length)
{
std::lock_guard<std::mutex> l(lock);
dout(10) << __func__ << " want_size " << want_size
<< " alloc_unit " << alloc_unit
<< " hint " << hint
dout(10) << __func__ << " want_size 0x" << std::hex << want_size
<< " alloc_unit 0x" << alloc_unit
<< " hint 0x" << hint << std::dec
<< dendl;
uint64_t want = MAX(alloc_unit, want_size);
int bin = _choose_bin(want);
Expand Down Expand Up @@ -160,30 +164,31 @@ int StupidAllocator::allocate(
uint64_t max =
alloc_unit * (rand() % g_conf->bluestore_debug_small_allocations);
if (max && *length > max) {
dout(10) << __func__ << " shortening allocation of " << *length << " -> "
<< max << " due to debug_small_allocations" << dendl;
dout(10) << __func__ << " shortening allocation of 0x" << std::hex
<< *length << " -> 0x"
<< max << " due to debug_small_allocations" << std::dec << dendl;
*length = max;
}
}
dout(30) << __func__ << " got " << *offset << "~" << *length << " from bin "
<< bin << dendl;
dout(30) << __func__ << " got 0x" << std::hex << *offset << "~" << *length
<< " from bin " << std::dec << bin << dendl;

free[bin].erase(*offset, *length);
uint64_t off, len;
if (*offset && free[bin].contains(*offset - skew - 1, &off, &len)) {
int newbin = _choose_bin(len);
if (newbin != bin) {
dout(30) << __func__ << " demoting " << off << "~" << len
<< " to bin " << newbin << dendl;
dout(30) << __func__ << " demoting 0x" << std::hex << off << "~" << len
<< std::dec << " to bin " << newbin << dendl;
free[bin].erase(off, len);
_insert_free(off, len);
}
}
if (free[bin].contains(*offset + *length, &off, &len)) {
int newbin = _choose_bin(len);
if (newbin != bin) {
dout(30) << __func__ << " demoting " << off << "~" << len
<< " to bin " << newbin << dendl;
dout(30) << __func__ << " demoting 0x" << std::hex << off << "~" << len
<< std::dec << " to bin " << newbin << dendl;
free[bin].erase(off, len);
_insert_free(off, len);
}
Expand Down Expand Up @@ -239,7 +244,8 @@ int StupidAllocator::release(
uint64_t offset, uint64_t length)
{
std::lock_guard<std::mutex> l(lock);
dout(10) << __func__ << " " << offset << "~" << length << dendl;
dout(10) << __func__ << " 0x" << std::hex << offset << "~" << length
<< std::dec << dendl;
uncommitted.insert(offset, length);
num_uncommitted += length;
return 0;
Expand All @@ -260,44 +266,50 @@ void StupidAllocator::dump(ostream& out)
for (auto p = free[bin].begin();
p != free[bin].end();
++p) {
dout(30) << __func__ << " " << p.get_start() << "~" << p.get_len() << dendl;
dout(30) << __func__ << " 0x" << std::hex << p.get_start() << "~"
<< p.get_len() << std::dec << dendl;
}
}
dout(30) << __func__ << " committing: "
<< committing.num_intervals() << " extents" << dendl;
for (auto p = committing.begin();
p != committing.end();
++p) {
dout(30) << __func__ << " " << p.get_start() << "~" << p.get_len() << dendl;
dout(30) << __func__ << " 0x" << std::hex << p.get_start() << "~"
<< p.get_len() << std::dec << dendl;
}
dout(30) << __func__ << " uncommitted: "
<< uncommitted.num_intervals() << " extents" << dendl;
for (auto p = uncommitted.begin();
p != uncommitted.end();
++p) {
dout(30) << __func__ << " " << p.get_start() << "~" << p.get_len() << dendl;
dout(30) << __func__ << " 0x" << std::hex << p.get_start() << "~"
<< p.get_len() << std::dec << dendl;
}
}

void StupidAllocator::init_add_free(uint64_t offset, uint64_t length)
{
std::lock_guard<std::mutex> l(lock);
dout(10) << __func__ << " " << offset << "~" << length << dendl;
dout(10) << __func__ << " 0x" << std::hex << offset << "~" << length
<< std::dec << dendl;
_insert_free(offset, length);
num_free += length;
}

void StupidAllocator::init_rm_free(uint64_t offset, uint64_t length)
{
std::lock_guard<std::mutex> l(lock);
dout(10) << __func__ << " " << offset << "~" << length << dendl;
dout(10) << __func__ << " 0x" << std::hex << offset << "~" << length
<< std::dec << dendl;
btree_interval_set<uint64_t> rm;
rm.insert(offset, length);
for (unsigned i = 0; i < free.size() && !rm.empty(); ++i) {
btree_interval_set<uint64_t> overlap;
overlap.intersection_of(rm, free[i]);
if (!overlap.empty()) {
dout(20) << __func__ << " bin " << i << " rm " << overlap << dendl;
dout(20) << __func__ << " bin " << i << " rm 0x" << std::hex << overlap
<< std::dec << dendl;
free[i].subtract(overlap);
rm.subtract(overlap);
}
Expand Down