mirror of https://github.com/schoebel/mars
trans_logger: fix replay_head refcounting, add paranoia
This commit is contained in:
parent
7e932641df
commit
782dfc97e4
|
@ -2663,6 +2663,7 @@ void replay_endio(struct generic_callback *cb)
|
||||||
{
|
{
|
||||||
struct trans_logger_mref_aspect *mref_a = cb->cb_private;
|
struct trans_logger_mref_aspect *mref_a = cb->cb_private;
|
||||||
struct trans_logger_brick *brick;
|
struct trans_logger_brick *brick;
|
||||||
|
bool ok;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
LAST_CALLBACK(cb);
|
LAST_CALLBACK(cb);
|
||||||
|
@ -2676,10 +2677,16 @@ void replay_endio(struct generic_callback *cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
traced_lock(&brick->replay_lock, flags);
|
traced_lock(&brick->replay_lock, flags);
|
||||||
|
ok = !list_empty(&mref_a->replay_head);
|
||||||
list_del_init(&mref_a->replay_head);
|
list_del_init(&mref_a->replay_head);
|
||||||
traced_unlock(&brick->replay_lock, flags);
|
traced_unlock(&brick->replay_lock, flags);
|
||||||
|
|
||||||
atomic_dec(&brick->replay_count);
|
if (likely(ok)) {
|
||||||
|
atomic_dec(&brick->replay_count);
|
||||||
|
} else {
|
||||||
|
MARS_ERR("callback with empty replay_head (replay_count=%d)\n", atomic_read(&brick->replay_count));
|
||||||
|
}
|
||||||
|
|
||||||
wake_up_interruptible_all(&brick->worker_event);
|
wake_up_interruptible_all(&brick->worker_event);
|
||||||
return;
|
return;
|
||||||
err:
|
err:
|
||||||
|
@ -2720,6 +2727,7 @@ void wait_replay(struct trans_logger_brick *brick, struct trans_logger_mref_aspe
|
||||||
const int max = 512; // limit parallelism somewhat
|
const int max = 512; // limit parallelism somewhat
|
||||||
int conflicts = 0;
|
int conflicts = 0;
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
bool was_empty;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
wait_event_interruptible_timeout(brick->worker_event,
|
wait_event_interruptible_timeout(brick->worker_event,
|
||||||
|
@ -2727,14 +2735,23 @@ void wait_replay(struct trans_logger_brick *brick, struct trans_logger_mref_aspe
|
||||||
&& (_has_conflict(brick, mref_a) ? conflicts++ : (ok = true), ok),
|
&& (_has_conflict(brick, mref_a) ? conflicts++ : (ok = true), ok),
|
||||||
60 * HZ);
|
60 * HZ);
|
||||||
|
|
||||||
atomic_inc(&brick->replay_count);
|
|
||||||
atomic_inc(&brick->total_replay_count);
|
atomic_inc(&brick->total_replay_count);
|
||||||
if (conflicts)
|
if (conflicts)
|
||||||
atomic_inc(&brick->total_replay_conflict_count);
|
atomic_inc(&brick->total_replay_conflict_count);
|
||||||
|
|
||||||
traced_lock(&brick->replay_lock, flags);
|
traced_lock(&brick->replay_lock, flags);
|
||||||
|
was_empty = !!list_empty(&mref_a->replay_head);
|
||||||
|
if (likely(was_empty)) {
|
||||||
|
atomic_inc(&brick->replay_count);
|
||||||
|
} else {
|
||||||
|
list_del(&mref_a->replay_head);
|
||||||
|
}
|
||||||
list_add(&mref_a->replay_head, &brick->replay_list);
|
list_add(&mref_a->replay_head, &brick->replay_list);
|
||||||
traced_unlock(&brick->replay_lock, flags);
|
traced_unlock(&brick->replay_lock, flags);
|
||||||
|
|
||||||
|
if (unlikely(!was_empty)) {
|
||||||
|
MARS_ERR("replay_head was already used (ok=%d, conflicts=%d, replay_count=%d)\n", ok, conflicts, atomic_read(&brick->replay_count));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline
|
static noinline
|
||||||
|
|
Loading…
Reference in New Issue