mirror of https://github.com/schoebel/mars
light: offload trans_logger from symlink update (deadlock prevention)
This commit is contained in:
parent
a036a01188
commit
7cc5c12436
|
@ -2448,8 +2448,6 @@ void _exit_inputs(struct trans_logger_brick *brick, bool force)
|
||||||
// no locking here: we should be the only thread doing this.
|
// no locking here: we should be the only thread doing this.
|
||||||
_inf_callback(input, true);
|
_inf_callback(input, true);
|
||||||
input->inf_last_jiffies = 0;
|
input->inf_last_jiffies = 0;
|
||||||
brick_string_free(input->inf.inf_host);
|
|
||||||
input->inf.inf_host = NULL;
|
|
||||||
input->inf.inf_is_applying = false;
|
input->inf.inf_is_applying = false;
|
||||||
input->inf.inf_is_logging = false;
|
input->inf.inf_is_logging = false;
|
||||||
input->is_operating = false;
|
input->is_operating = false;
|
||||||
|
@ -3199,8 +3197,6 @@ static noinline
|
||||||
int trans_logger_input_destruct(struct trans_logger_input *input)
|
int trans_logger_input_destruct(struct trans_logger_input *input)
|
||||||
{
|
{
|
||||||
CHECK_HEAD_EMPTY(&input->pos_list);
|
CHECK_HEAD_EMPTY(&input->pos_list);
|
||||||
brick_string_free(input->inf.inf_host);
|
|
||||||
input->inf.inf_host = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,11 +206,13 @@ struct trans_logger_output {
|
||||||
MARS_OUTPUT(trans_logger);
|
MARS_OUTPUT(trans_logger);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_HOST_LEN 32
|
||||||
|
|
||||||
struct trans_logger_info {
|
struct trans_logger_info {
|
||||||
// to be maintained / initialized from outside
|
// to be maintained / initialized from outside
|
||||||
void (*inf_callback)(struct trans_logger_info *inf);
|
void (*inf_callback)(struct trans_logger_info *inf);
|
||||||
void *inf_private;
|
void *inf_private;
|
||||||
char *inf_host;
|
char inf_host[MAX_HOST_LEN];
|
||||||
int inf_sequence; // logfile sequence number
|
int inf_sequence; // logfile sequence number
|
||||||
|
|
||||||
// maintained by trans_logger
|
// maintained by trans_logger
|
||||||
|
|
|
@ -71,6 +71,8 @@ struct light_class {
|
||||||
|
|
||||||
// needed for logfile rotation
|
// needed for logfile rotation
|
||||||
|
|
||||||
|
#define MAX_INFOS 4
|
||||||
|
|
||||||
struct mars_rotate {
|
struct mars_rotate {
|
||||||
struct mars_global *global;
|
struct mars_global *global;
|
||||||
struct copy_brick *sync_brick;
|
struct copy_brick *sync_brick;
|
||||||
|
@ -95,7 +97,6 @@ struct mars_rotate {
|
||||||
struct mars_limiter replay_limiter;
|
struct mars_limiter replay_limiter;
|
||||||
struct mars_limiter sync_limiter;
|
struct mars_limiter sync_limiter;
|
||||||
struct mars_limiter file_limiter;
|
struct mars_limiter file_limiter;
|
||||||
struct semaphore inf_mutex;
|
|
||||||
int inf_prev_sequence;
|
int inf_prev_sequence;
|
||||||
long long flip_start;
|
long long flip_start;
|
||||||
loff_t dev_size;
|
loff_t dev_size;
|
||||||
|
@ -116,6 +117,9 @@ struct mars_rotate {
|
||||||
bool is_primary;
|
bool is_primary;
|
||||||
bool old_is_primary;
|
bool old_is_primary;
|
||||||
bool copy_is_done;
|
bool copy_is_done;
|
||||||
|
spinlock_t inf_lock;
|
||||||
|
bool infs_is_dirty[MAX_INFOS];
|
||||||
|
struct trans_logger_info infs[MAX_INFOS];
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
@ -603,13 +607,14 @@ static
|
||||||
void _update_info(struct trans_logger_info *inf)
|
void _update_info(struct trans_logger_info *inf)
|
||||||
{
|
{
|
||||||
struct mars_rotate *rot = inf->inf_private;
|
struct mars_rotate *rot = inf->inf_private;
|
||||||
|
int hash;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (unlikely(!rot)) {
|
if (unlikely(!rot)) {
|
||||||
MARS_ERR("rot is NULL\n");
|
MARS_ERR("rot is NULL\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&rot->inf_mutex);
|
|
||||||
|
|
||||||
MARS_DBG("inf = %p '%s' seq = %d min_pos = %lld max_pos = %lld log_pos = %lld is_applying = %d is_logging = %d\n",
|
MARS_DBG("inf = %p '%s' seq = %d min_pos = %lld max_pos = %lld log_pos = %lld is_applying = %d is_logging = %d\n",
|
||||||
inf,
|
inf,
|
||||||
SAFE_STR(inf->inf_host),
|
SAFE_STR(inf->inf_host),
|
||||||
|
@ -620,40 +625,93 @@ void _update_info(struct trans_logger_info *inf)
|
||||||
inf->inf_is_applying,
|
inf->inf_is_applying,
|
||||||
inf->inf_is_logging);
|
inf->inf_is_logging);
|
||||||
|
|
||||||
if (inf->inf_is_logging || inf->inf_is_applying) {
|
hash = inf->inf_sequence % MAX_INFOS;
|
||||||
_update_replay_link(rot, inf);
|
if (unlikely(rot->infs_is_dirty[hash])) {
|
||||||
|
if (unlikely(rot->infs[hash].inf_sequence != inf->inf_sequence)) {
|
||||||
|
MARS_ERR("buffer %d: sequence trash %d -> %d. is the mar_light thread hanging?\n", hash, rot->infs[hash].inf_sequence, inf->inf_sequence);
|
||||||
|
} else {
|
||||||
|
MARS_DBG("buffer %d is overwritten (sequence=%d)\n", hash, inf->inf_sequence);
|
||||||
}
|
}
|
||||||
if (inf->inf_is_logging || inf->inf_is_applying) {
|
|
||||||
_update_version_link(rot, inf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
up(&rot->inf_mutex);
|
traced_lock(&rot->inf_lock, flags);
|
||||||
|
memcpy(&rot->infs[hash], inf, sizeof(struct trans_logger_info));
|
||||||
|
rot->infs_is_dirty[hash] = true;
|
||||||
|
traced_unlock(&rot->inf_lock, flags);
|
||||||
|
|
||||||
|
mars_trigger();
|
||||||
done:;
|
done:;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void write_info_links(struct mars_rotate *rot)
|
||||||
|
{
|
||||||
|
struct trans_logger_info inf;
|
||||||
|
int count = 0;
|
||||||
|
for (;;) {
|
||||||
|
unsigned long flags;
|
||||||
|
int hash = -1;
|
||||||
|
int min = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
traced_lock(&rot->inf_lock, flags);
|
||||||
|
for (i = 0; i < MAX_INFOS; i++) {
|
||||||
|
if (!rot->infs_is_dirty[i])
|
||||||
|
continue;
|
||||||
|
if (!min || min > rot->infs[i].inf_sequence) {
|
||||||
|
min = rot->infs[i].inf_sequence;
|
||||||
|
hash = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash < 0) {
|
||||||
|
traced_unlock(&rot->inf_lock, flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rot->infs_is_dirty[hash] = false;
|
||||||
|
memcpy(&inf, &rot->infs[hash], sizeof(struct trans_logger_info));
|
||||||
|
traced_unlock(&rot->inf_lock, flags);
|
||||||
|
|
||||||
|
MARS_DBG("seq = %d min_pos = %lld max_pos = %lld log_pos = %lld is_applying = %d is_logging = %d\n",
|
||||||
|
inf.inf_sequence,
|
||||||
|
inf.inf_min_pos,
|
||||||
|
inf.inf_max_pos,
|
||||||
|
inf.inf_log_pos,
|
||||||
|
inf.inf_is_applying,
|
||||||
|
inf.inf_is_logging);
|
||||||
|
|
||||||
|
if (inf.inf_is_logging || inf.inf_is_applying) {
|
||||||
|
_update_replay_link(rot, &inf);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (inf.inf_is_logging || inf.inf_is_applying) {
|
||||||
|
_update_version_link(rot, &inf);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count)
|
||||||
|
mars_remote_trigger();
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void _make_new_replaylink(struct mars_rotate *rot, char *new_host, int new_sequence, loff_t end_pos)
|
void _make_new_replaylink(struct mars_rotate *rot, char *new_host, int new_sequence, loff_t end_pos)
|
||||||
{
|
{
|
||||||
struct trans_logger_info inf = {
|
struct trans_logger_info inf = {
|
||||||
.inf_private = rot,
|
.inf_private = rot,
|
||||||
.inf_host = new_host,
|
|
||||||
.inf_sequence = new_sequence,
|
.inf_sequence = new_sequence,
|
||||||
.inf_min_pos = 0,
|
.inf_min_pos = 0,
|
||||||
.inf_max_pos = 0,
|
.inf_max_pos = 0,
|
||||||
.inf_log_pos = end_pos,
|
.inf_log_pos = end_pos,
|
||||||
.inf_is_applying = true,
|
.inf_is_applying = true,
|
||||||
};
|
};
|
||||||
|
strncpy(inf.inf_host, new_host, sizeof(inf.inf_host));
|
||||||
down(&rot->inf_mutex);
|
|
||||||
|
|
||||||
MARS_DBG("new_host = '%s' new_sequence = %d end_pos = %lld\n", new_host, new_sequence, end_pos);
|
MARS_DBG("new_host = '%s' new_sequence = %d end_pos = %lld\n", new_host, new_sequence, end_pos);
|
||||||
|
|
||||||
_update_replay_link(rot, &inf);
|
_update_replay_link(rot, &inf);
|
||||||
_update_version_link(rot, &inf);
|
_update_version_link(rot, &inf);
|
||||||
|
|
||||||
up(&rot->inf_mutex);
|
|
||||||
|
|
||||||
#ifdef CONFIG_MARS_FAST_TRIGGER
|
#ifdef CONFIG_MARS_FAST_TRIGGER
|
||||||
mars_trigger();
|
mars_trigger();
|
||||||
mars_remote_trigger();
|
mars_remote_trigger();
|
||||||
|
@ -1692,6 +1750,7 @@ void rot_destruct(void *_rot)
|
||||||
{
|
{
|
||||||
struct mars_rotate *rot = _rot;
|
struct mars_rotate *rot = _rot;
|
||||||
if (likely(rot)) {
|
if (likely(rot)) {
|
||||||
|
write_info_links(rot);
|
||||||
brick_string_free(rot->copy_path);
|
brick_string_free(rot->copy_path);
|
||||||
brick_string_free(rot->parent_path);
|
brick_string_free(rot->parent_path);
|
||||||
rot->copy_path = NULL;
|
rot->copy_path = NULL;
|
||||||
|
@ -1734,7 +1793,7 @@ int make_log_init(void *buf, struct mars_dent *dent)
|
||||||
status = -ENOMEM;
|
status = -ENOMEM;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
sema_init(&rot->inf_mutex, 1);
|
spin_lock_init(&rot->inf_lock);
|
||||||
copy_path = path_make("%s/logfile-update", parent_path);
|
copy_path = path_make("%s/logfile-update", parent_path);
|
||||||
if (unlikely(!copy_path)) {
|
if (unlikely(!copy_path)) {
|
||||||
MARS_ERR("cannot create copy_path\n");
|
MARS_ERR("cannot create copy_path\n");
|
||||||
|
@ -1766,6 +1825,8 @@ int make_log_init(void *buf, struct mars_dent *dent)
|
||||||
if (!rot->parent_path)
|
if (!rot->parent_path)
|
||||||
rot->parent_path =brick_strdup(parent_path);
|
rot->parent_path =brick_strdup(parent_path);
|
||||||
|
|
||||||
|
write_info_links(rot);
|
||||||
|
|
||||||
mars_remaining_space(parent_path, &rot->total_space, &rot->remaining_space);
|
mars_remaining_space(parent_path, &rot->total_space, &rot->remaining_space);
|
||||||
|
|
||||||
/* Fetch the replay status symlink.
|
/* Fetch the replay status symlink.
|
||||||
|
@ -1796,7 +1857,7 @@ int make_log_init(void *buf, struct mars_dent *dent)
|
||||||
*/
|
*/
|
||||||
if (rot->trans_brick) {
|
if (rot->trans_brick) {
|
||||||
struct trans_logger_input *trans_input = rot->trans_brick->inputs[rot->trans_brick->old_input_nr];
|
struct trans_logger_input *trans_input = rot->trans_brick->inputs[rot->trans_brick->old_input_nr];
|
||||||
if (trans_input && trans_input->is_operating && trans_input->inf.inf_host) {
|
if (trans_input && trans_input->is_operating) {
|
||||||
aio_path = path_make("%s/log-%09d-%s", parent_path, trans_input->inf.inf_sequence, trans_input->inf.inf_host);
|
aio_path = path_make("%s/log-%09d-%s", parent_path, trans_input->inf.inf_sequence, trans_input->inf.inf_host);
|
||||||
MARS_DBG("using logfile '%s' from trans_input %d (new=%d)\n", SAFE_STR(aio_path), rot->trans_brick->old_input_nr, rot->trans_brick->log_input_nr);
|
MARS_DBG("using logfile '%s' from trans_input %d (new=%d)\n", SAFE_STR(aio_path), rot->trans_brick->old_input_nr, rot->trans_brick->log_input_nr);
|
||||||
}
|
}
|
||||||
|
@ -2180,11 +2241,10 @@ void _init_trans_input(struct trans_logger_input *trans_input, struct mars_dent
|
||||||
MARS_ERR("this should not happen\n");
|
MARS_ERR("this should not happen\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
brick_string_free(trans_input->inf.inf_host); // just for safety
|
|
||||||
|
|
||||||
memset(&trans_input->inf, 0, sizeof(trans_input->inf));
|
memset(&trans_input->inf, 0, sizeof(trans_input->inf));
|
||||||
|
|
||||||
trans_input->inf.inf_host = brick_strdup(log_dent->d_rest);
|
strncpy(trans_input->inf.inf_host, log_dent->d_rest, sizeof(trans_input->inf.inf_host));
|
||||||
trans_input->inf.inf_sequence = log_dent->d_serial;
|
trans_input->inf.inf_sequence = log_dent->d_serial;
|
||||||
trans_input->inf.inf_private = rot;
|
trans_input->inf.inf_private = rot;
|
||||||
trans_input->inf.inf_callback = _update_info;
|
trans_input->inf.inf_callback = _update_info;
|
||||||
|
|
Loading…
Reference in New Issue