If a crash occurs during flushing a redirect-write it may happen so that
the disk contains both old and new metadata entries. This is OK, but prior
to 0.8.0 after this situation OSDs started without problem, but then they
crashed after some more overwrites with a "tried to overwrite non-zero
metadata entry" error. 0.8.0 introduced a change that was intended to fix
this situation, but rather than fixing it it prevented OSDs from starting,
now because of a "big_write journal_entry was allocated over another object"
error... :-)
This change finally fixes the original issue.
Followup to 54ef2c389f
70 lines
1.8 KiB
C++
70 lines
1.8 KiB
C++
// Copyright (c) Vitaliy Filippov, 2019+
|
|
// License: VNPL-1.1 (see README.md for details)
|
|
|
|
#pragma once
|
|
|
|
struct blockstore_init_meta_buf
|
|
{
|
|
uint8_t *buf = NULL;
|
|
uint64_t size = 0;
|
|
uint64_t offset = 0;
|
|
int state = 0;
|
|
};
|
|
|
|
class blockstore_init_meta
|
|
{
|
|
blockstore_impl_t *bs;
|
|
int wait_state = 0;
|
|
bool zero_on_init = false;
|
|
void *metadata_buffer = NULL;
|
|
blockstore_init_meta_buf bufs[2] = {};
|
|
int submitted = 0;
|
|
struct io_uring_sqe *sqe;
|
|
struct ring_data_t *data;
|
|
uint64_t md_offset = 0;
|
|
uint64_t next_offset = 0;
|
|
uint64_t entries_loaded = 0;
|
|
unsigned entries_per_block = 0;
|
|
int i = 0, j = 0;
|
|
std::vector<uint64_t> entries_to_zero;
|
|
bool handle_meta_block(uint8_t *buf, uint64_t count, uint64_t done_cnt);
|
|
void handle_event(ring_data_t *data, int buf_num);
|
|
public:
|
|
blockstore_init_meta(blockstore_impl_t *bs);
|
|
int loop();
|
|
};
|
|
|
|
struct bs_init_journal_done
|
|
{
|
|
void *buf;
|
|
uint64_t pos, len;
|
|
};
|
|
|
|
class blockstore_init_journal
|
|
{
|
|
blockstore_impl_t *bs;
|
|
int wait_state = 0, wait_count = 0, handle_res = 0;
|
|
uint64_t entries_loaded = 0;
|
|
uint32_t crc32_last = 0;
|
|
bool started = false;
|
|
uint64_t next_free;
|
|
std::vector<bs_init_journal_done> done;
|
|
std::vector<obj_ver_id> double_allocs;
|
|
uint64_t journal_pos = 0;
|
|
uint64_t continue_pos = 0;
|
|
void *init_write_buf = NULL;
|
|
uint64_t init_write_sector = 0;
|
|
bool wrapped = false;
|
|
void *submitted_buf;
|
|
struct io_uring_sqe *sqe;
|
|
struct ring_data_t *data;
|
|
journal_entry_start *je_start;
|
|
std::function<void(ring_data_t*)> simple_callback;
|
|
int handle_journal_part(void *buf, uint64_t done_pos, uint64_t len);
|
|
void handle_event(ring_data_t *data);
|
|
void erase_dirty_object(blockstore_dirty_db_t::iterator dirty_it);
|
|
public:
|
|
blockstore_init_journal(blockstore_impl_t* bs);
|
|
int loop();
|
|
};
|