Skip double allocs when reading journal
parent
f4769ba7c7
commit
ad9f619370
|
@ -37,6 +37,21 @@ allocator::~allocator()
|
||||||
delete[] mask;
|
delete[] mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool allocator::get(uint64_t addr)
|
||||||
|
{
|
||||||
|
if (addr >= size)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint64_t p2 = 1, offset = 0;
|
||||||
|
while (p2 * 64 < size)
|
||||||
|
{
|
||||||
|
offset += p2;
|
||||||
|
p2 = p2 * 64;
|
||||||
|
}
|
||||||
|
return ((mask[offset + addr/64] >> (addr % 64)) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
void allocator::set(uint64_t addr, bool value)
|
void allocator::set(uint64_t addr, bool value)
|
||||||
{
|
{
|
||||||
if (addr >= size)
|
if (addr >= size)
|
||||||
|
|
|
@ -16,6 +16,7 @@ class allocator
|
||||||
public:
|
public:
|
||||||
allocator(uint64_t blocks);
|
allocator(uint64_t blocks);
|
||||||
~allocator();
|
~allocator();
|
||||||
|
bool get(uint64_t addr);
|
||||||
void set(uint64_t addr, bool value);
|
void set(uint64_t addr, bool value);
|
||||||
uint64_t find_free();
|
uint64_t find_free();
|
||||||
uint64_t get_free_count();
|
uint64_t get_free_count();
|
||||||
|
|
|
@ -402,6 +402,18 @@ resume_1:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto ov: double_allocs)
|
||||||
|
{
|
||||||
|
auto dirty_it = bs->dirty_db.find(ov);
|
||||||
|
if (dirty_it != bs->dirty_db.end() &&
|
||||||
|
IS_BIG_WRITE(dirty_it->second.state) &&
|
||||||
|
dirty_it->second.location == UINT64_MAX)
|
||||||
|
{
|
||||||
|
printf("Fatal error (bug): %lx:%lx v%lu big_write journal_entry was allocated over another object\n",
|
||||||
|
dirty_it->first.oid.inode, dirty_it->first.oid.stripe, dirty_it->first.version);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
bs->flusher->mark_trim_possible();
|
bs->flusher->mark_trim_possible();
|
||||||
bs->journal.dirty_start = bs->journal.next_free;
|
bs->journal.dirty_start = bs->journal.next_free;
|
||||||
printf(
|
printf(
|
||||||
|
@ -597,22 +609,32 @@ int blockstore_init_journal::handle_journal_part(void *buf, uint64_t done_pos, u
|
||||||
.oid = je->big_write.oid,
|
.oid = je->big_write.oid,
|
||||||
.version = je->big_write.version,
|
.version = je->big_write.version,
|
||||||
};
|
};
|
||||||
bs->dirty_db.emplace(ov, (dirty_entry){
|
auto dirty_it = bs->dirty_db.emplace(ov, (dirty_entry){
|
||||||
.state = (BS_ST_BIG_WRITE | BS_ST_SYNCED),
|
.state = (BS_ST_BIG_WRITE | BS_ST_SYNCED),
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.location = je->big_write.location,
|
.location = je->big_write.location,
|
||||||
.offset = je->big_write.offset,
|
.offset = je->big_write.offset,
|
||||||
.len = je->big_write.len,
|
.len = je->big_write.len,
|
||||||
.journal_sector = proc_pos,
|
.journal_sector = proc_pos,
|
||||||
});
|
}).first;
|
||||||
|
if (bs->data_alloc->get(je->big_write.location >> bs->block_order))
|
||||||
|
{
|
||||||
|
// This is probably a big_write that's already flushed and freed, but it may
|
||||||
|
// also indicate a bug. So we remember such entries and recheck them afterwards
|
||||||
|
dirty_it->second.location = UINT64_MAX;
|
||||||
|
double_allocs.push_back(ov);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
#ifdef BLOCKSTORE_DEBUG
|
||||||
printf(
|
printf(
|
||||||
"Allocate block (journal) %lu: %lx:%lx v%lu\n",
|
"Allocate block (journal) %lu: %lx:%lx v%lu\n",
|
||||||
je->big_write.location >> bs->block_order,
|
je->big_write.location >> bs->block_order,
|
||||||
ov.oid.inode, ov.oid.stripe, ov.version
|
ov.oid.inode, ov.oid.stripe, ov.version
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
bs->data_alloc->set(je->big_write.location >> bs->block_order, true);
|
bs->data_alloc->set(je->big_write.location >> bs->block_order, true);
|
||||||
|
}
|
||||||
bs->journal.used_sectors[proc_pos]++;
|
bs->journal.used_sectors[proc_pos]++;
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
#ifdef BLOCKSTORE_DEBUG
|
||||||
printf(
|
printf(
|
||||||
|
|
|
@ -36,6 +36,7 @@ class blockstore_init_journal
|
||||||
bool started = false;
|
bool started = false;
|
||||||
uint64_t next_free;
|
uint64_t next_free;
|
||||||
std::vector<bs_init_journal_done> done;
|
std::vector<bs_init_journal_done> done;
|
||||||
|
std::vector<obj_ver_id> double_allocs;
|
||||||
uint64_t journal_pos = 0;
|
uint64_t journal_pos = 0;
|
||||||
uint64_t continue_pos = 0;
|
uint64_t continue_pos = 0;
|
||||||
void *init_write_buf = NULL;
|
void *init_write_buf = NULL;
|
||||||
|
|
|
@ -248,7 +248,8 @@ void blockstore_impl_t::erase_dirty(blockstore_dirty_db_t::iterator dirty_start,
|
||||||
}
|
}
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (IS_BIG_WRITE(dirty_it->second.state) && dirty_it->second.location != clean_loc)
|
if (IS_BIG_WRITE(dirty_it->second.state) && dirty_it->second.location != clean_loc &&
|
||||||
|
dirty_it->second.location != UINT64_MAX)
|
||||||
{
|
{
|
||||||
#ifdef BLOCKSTORE_DEBUG
|
#ifdef BLOCKSTORE_DEBUG
|
||||||
printf("Free block %lu from %lx:%lx v%lu\n", dirty_it->second.location >> block_order,
|
printf("Free block %lu from %lx:%lx v%lu\n", dirty_it->second.location >> block_order,
|
||||||
|
|
|
@ -20,7 +20,15 @@ void alloc_all(int size)
|
||||||
{
|
{
|
||||||
printf("incorrect block allocated: expected %d, got %lu\n", i, x);
|
printf("incorrect block allocated: expected %d, got %lu\n", i, x);
|
||||||
}
|
}
|
||||||
|
if (a->get(x))
|
||||||
|
{
|
||||||
|
printf("not free before set at %d\n", i);
|
||||||
|
}
|
||||||
a->set(x, true);
|
a->set(x, true);
|
||||||
|
if (!a->get(x))
|
||||||
|
{
|
||||||
|
printf("free after set at %d\n", i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uint64_t x = a->find_free();
|
uint64_t x = a->find_free();
|
||||||
if (x != UINT64_MAX)
|
if (x != UINT64_MAX)
|
||||||
|
|
Loading…
Reference in New Issue