Fix "tried to overwrite non-zero metadata entry" when during a previous metadata

flush writing new entry is completed, but zeroing out an old one isn't
Vitaliy Filippov 2022-08-21 00:31:18 +03:00
parent 29b40aba93
commit d83580bd68
3 changed files with 28 additions and 2 deletions

View File

@ -211,8 +211,9 @@ resume_1:
return 0;
}
void blockstore_init_meta::handle_entries(void* entries, unsigned count, int block_order)
bool blockstore_init_meta::handle_entries(void* entries, unsigned count, int block_order)
{
bool updated = false;
for (unsigned i = 0; i < count; i++)
{
clean_disk_entry *entry = (clean_disk_entry*)((uint8_t*)entries + i*bs->dsk.clean_entry_size);
@ -229,6 +230,11 @@ void blockstore_init_meta::handle_entries(void* entries, unsigned count, int blo
if (clean_it != clean_db.end())
{
// free the previous block
// here we have to zero out the entry because otherwise we'll hit
// "tried to overwrite non-zero metadata entry" later
// FIXME: Write it back if modified with inmemory_meta == false
updated = true;
memset(entry, 0, bs->dsk.clean_entry_size);
#ifdef BLOCKSTORE_DEBUG
printf("Free block %lu from %lx:%lx v%lu (new location is %lu)\n",
clean_it->second.location >> block_order,
@ -253,12 +259,16 @@ void blockstore_init_meta::handle_entries(void* entries, unsigned count, int blo
}
else
{
// here we also have to zero out the entry
updated = true;
memset(entry, 0, bs->dsk.clean_entry_size);
#ifdef BLOCKSTORE_DEBUG
printf("Old clean entry %lu: %lx:%lx v%lu\n", done_cnt+i, entry->oid.inode, entry->oid.stripe, entry->version);
#endif
}
}
}
return updated;
}
blockstore_init_journal::blockstore_init_journal(blockstore_impl_t *bs)

View File

@ -15,7 +15,7 @@ class blockstore_init_meta
uint64_t entries_loaded = 0;
struct io_uring_sqe *sqe;
struct ring_data_t *data;
void handle_entries(void *entries, unsigned count, int block_order);
bool handle_entries(void *entries, unsigned count, int block_order);
void handle_event(ring_data_t *data);
public:
blockstore_init_meta(blockstore_impl_t *bs);

View File

@ -269,6 +269,22 @@ int blockstore_impl_t::dequeue_write(blockstore_op_t *op)
cancel_all_writes(op, dirty_it, -ENOSPC);
return 2;
}
if (inmemory_meta)
{
// Check once more that metadata entry is zeroed (the reverse means a bug or corruption)
uint64_t sector = (loc / (dsk.meta_block_size / dsk.clean_entry_size)) * dsk.meta_block_size;
uint64_t pos = (loc % (dsk.meta_block_size / dsk.clean_entry_size));
clean_disk_entry *entry = (clean_disk_entry*)((uint8_t*)metadata_buffer + sector + pos*dsk.clean_entry_size);
if (entry->oid.inode || entry->oid.stripe || entry->version)
{
printf(
"Fatal error (metadata corruption or bug): tried to write object %lx:%lx v%lu"
" over a non-zero metadata entry %lu with %lx:%lx v%lu\n", op->oid.inode,
op->oid.stripe, op->version, loc, entry->oid.inode, entry->oid.stripe, entry->version
);
exit(1);
}
}
BS_SUBMIT_GET_SQE(sqe, data);
write_iodepth++;
dirty_it->second.location = loc << dsk.block_order;