Commit 650db8a8 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: trans->locked

Add a field for tracking whether a transaction object holds btree locks,
and assertions to verify state.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent e2e568bd
...@@ -999,6 +999,7 @@ static int bch2_btree_path_traverse_all(struct btree_trans *trans) ...@@ -999,6 +999,7 @@ static int bch2_btree_path_traverse_all(struct btree_trans *trans)
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
cond_resched(); cond_resched();
trans->locked = true;
if (unlikely(trans->memory_allocation_failure)) { if (unlikely(trans->memory_allocation_failure)) {
struct closure cl; struct closure cl;
...@@ -3023,7 +3024,8 @@ u32 bch2_trans_begin(struct btree_trans *trans) ...@@ -3023,7 +3024,8 @@ u32 bch2_trans_begin(struct btree_trans *trans)
if (!trans->restarted && if (!trans->restarted &&
(need_resched() || (need_resched() ||
time_after64(now, trans->last_begin_time + BTREE_TRANS_MAX_LOCK_HOLD_TIME_NS))) { time_after64(now, trans->last_begin_time + BTREE_TRANS_MAX_LOCK_HOLD_TIME_NS))) {
drop_locks_do(trans, (cond_resched(), 0)); bch2_trans_unlock(trans);
cond_resched();
now = local_clock(); now = local_clock();
} }
trans->last_begin_time = now; trans->last_begin_time = now;
...@@ -3033,6 +3035,8 @@ u32 bch2_trans_begin(struct btree_trans *trans) ...@@ -3033,6 +3035,8 @@ u32 bch2_trans_begin(struct btree_trans *trans)
bch2_trans_srcu_unlock(trans); bch2_trans_srcu_unlock(trans);
trans->last_begin_ip = _RET_IP_; trans->last_begin_ip = _RET_IP_;
trans->locked = true;
if (trans->restarted) { if (trans->restarted) {
bch2_btree_path_traverse_all(trans); bch2_btree_path_traverse_all(trans);
trans->notrace_relock_fail = false; trans->notrace_relock_fail = false;
...@@ -3090,7 +3094,7 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx) ...@@ -3090,7 +3094,7 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
*/ */
BUG_ON(pos_task && BUG_ON(pos_task &&
pid == pos_task->pid && pid == pos_task->pid &&
bch2_trans_locked(pos)); pos->locked);
if (pos_task && pid < pos_task->pid) { if (pos_task && pid < pos_task->pid) {
list_add_tail(&trans->list, &pos->list); list_add_tail(&trans->list, &pos->list);
...@@ -3106,6 +3110,7 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx) ...@@ -3106,6 +3110,7 @@ struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
trans->last_begin_time = local_clock(); trans->last_begin_time = local_clock();
trans->fn_idx = fn_idx; trans->fn_idx = fn_idx;
trans->locking_wait.task = current; trans->locking_wait.task = current;
trans->locked = true;
trans->journal_replay_not_finished = trans->journal_replay_not_finished =
unlikely(!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)) && unlikely(!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags)) &&
atomic_inc_not_zero(&c->journal_keys.ref); atomic_inc_not_zero(&c->journal_keys.ref);
......
...@@ -286,7 +286,6 @@ int bch2_trans_relock(struct btree_trans *); ...@@ -286,7 +286,6 @@ int bch2_trans_relock(struct btree_trans *);
int bch2_trans_relock_notrace(struct btree_trans *); int bch2_trans_relock_notrace(struct btree_trans *);
void bch2_trans_unlock(struct btree_trans *); void bch2_trans_unlock(struct btree_trans *);
void bch2_trans_unlock_long(struct btree_trans *); void bch2_trans_unlock_long(struct btree_trans *);
bool bch2_trans_locked(struct btree_trans *);
static inline int trans_was_restarted(struct btree_trans *trans, u32 restart_count) static inline int trans_was_restarted(struct btree_trans *trans, u32 restart_count)
{ {
......
...@@ -490,8 +490,6 @@ static inline bool btree_path_get_locks(struct btree_trans *trans, ...@@ -490,8 +490,6 @@ static inline bool btree_path_get_locks(struct btree_trans *trans,
if (path->uptodate == BTREE_ITER_NEED_RELOCK) if (path->uptodate == BTREE_ITER_NEED_RELOCK)
path->uptodate = BTREE_ITER_UPTODATE; path->uptodate = BTREE_ITER_UPTODATE;
bch2_trans_verify_locks(trans);
return path->uptodate < BTREE_ITER_NEED_RELOCK; return path->uptodate < BTREE_ITER_NEED_RELOCK;
} }
...@@ -607,7 +605,9 @@ bool bch2_btree_path_relock_norestart(struct btree_trans *trans, struct btree_pa ...@@ -607,7 +605,9 @@ bool bch2_btree_path_relock_norestart(struct btree_trans *trans, struct btree_pa
{ {
struct get_locks_fail f; struct get_locks_fail f;
return btree_path_get_locks(trans, path, false, &f); bool ret = btree_path_get_locks(trans, path, false, &f);
bch2_trans_verify_locks(trans);
return ret;
} }
int __bch2_btree_path_relock(struct btree_trans *trans, int __bch2_btree_path_relock(struct btree_trans *trans,
...@@ -630,7 +630,9 @@ bool bch2_btree_path_upgrade_noupgrade_sibs(struct btree_trans *trans, ...@@ -630,7 +630,9 @@ bool bch2_btree_path_upgrade_noupgrade_sibs(struct btree_trans *trans,
path->locks_want = new_locks_want; path->locks_want = new_locks_want;
return btree_path_get_locks(trans, path, true, f); bool ret = btree_path_get_locks(trans, path, true, f);
bch2_trans_verify_locks(trans);
return ret;
} }
bool __bch2_btree_path_upgrade(struct btree_trans *trans, bool __bch2_btree_path_upgrade(struct btree_trans *trans,
...@@ -638,8 +640,9 @@ bool __bch2_btree_path_upgrade(struct btree_trans *trans, ...@@ -638,8 +640,9 @@ bool __bch2_btree_path_upgrade(struct btree_trans *trans,
unsigned new_locks_want, unsigned new_locks_want,
struct get_locks_fail *f) struct get_locks_fail *f)
{ {
if (bch2_btree_path_upgrade_noupgrade_sibs(trans, path, new_locks_want, f)) bool ret = bch2_btree_path_upgrade_noupgrade_sibs(trans, path, new_locks_want, f);
return true; if (ret)
goto out;
/* /*
* XXX: this is ugly - we'd prefer to not be mucking with other * XXX: this is ugly - we'd prefer to not be mucking with other
...@@ -673,8 +676,9 @@ bool __bch2_btree_path_upgrade(struct btree_trans *trans, ...@@ -673,8 +676,9 @@ bool __bch2_btree_path_upgrade(struct btree_trans *trans,
btree_path_get_locks(trans, linked, true, NULL); btree_path_get_locks(trans, linked, true, NULL);
} }
} }
out:
return false; bch2_trans_verify_locks(trans);
return ret;
} }
void __bch2_btree_path_downgrade(struct btree_trans *trans, void __bch2_btree_path_downgrade(struct btree_trans *trans,
...@@ -774,6 +778,8 @@ static inline int __bch2_trans_relock(struct btree_trans *trans, bool trace) ...@@ -774,6 +778,8 @@ static inline int __bch2_trans_relock(struct btree_trans *trans, bool trace)
if (unlikely(trans->restarted)) if (unlikely(trans->restarted))
return -((int) trans->restarted); return -((int) trans->restarted);
if (unlikely(trans->locked))
goto out;
trans_for_each_path(trans, path, i) { trans_for_each_path(trans, path, i) {
struct get_locks_fail f; struct get_locks_fail f;
...@@ -783,6 +789,8 @@ static inline int __bch2_trans_relock(struct btree_trans *trans, bool trace) ...@@ -783,6 +789,8 @@ static inline int __bch2_trans_relock(struct btree_trans *trans, bool trace)
return bch2_trans_relock_fail(trans, path, &f, trace); return bch2_trans_relock_fail(trans, path, &f, trace);
} }
trans->locked = true;
out:
bch2_trans_verify_locks(trans); bch2_trans_verify_locks(trans);
return 0; return 0;
} }
...@@ -800,11 +808,17 @@ int bch2_trans_relock_notrace(struct btree_trans *trans) ...@@ -800,11 +808,17 @@ int bch2_trans_relock_notrace(struct btree_trans *trans)
void bch2_trans_unlock_noassert(struct btree_trans *trans) void bch2_trans_unlock_noassert(struct btree_trans *trans)
{ {
__bch2_trans_unlock(trans); __bch2_trans_unlock(trans);
trans->locked = false;
trans->last_unlock_ip = _RET_IP_;
} }
void bch2_trans_unlock(struct btree_trans *trans) void bch2_trans_unlock(struct btree_trans *trans)
{ {
__bch2_trans_unlock(trans); __bch2_trans_unlock(trans);
trans->locked = false;
trans->last_unlock_ip = _RET_IP_;
} }
void bch2_trans_unlock_long(struct btree_trans *trans) void bch2_trans_unlock_long(struct btree_trans *trans)
...@@ -813,17 +827,6 @@ void bch2_trans_unlock_long(struct btree_trans *trans) ...@@ -813,17 +827,6 @@ void bch2_trans_unlock_long(struct btree_trans *trans)
bch2_trans_srcu_unlock(trans); bch2_trans_srcu_unlock(trans);
} }
bool bch2_trans_locked(struct btree_trans *trans)
{
struct btree_path *path;
unsigned i;
trans_for_each_path(trans, path, i)
if (path->nodes_locked)
return true;
return false;
}
int __bch2_trans_mutex_lock(struct btree_trans *trans, int __bch2_trans_mutex_lock(struct btree_trans *trans,
struct mutex *lock) struct mutex *lock)
{ {
...@@ -865,6 +868,17 @@ void bch2_btree_path_verify_locks(struct btree_path *path) ...@@ -865,6 +868,17 @@ void bch2_btree_path_verify_locks(struct btree_path *path)
} }
} }
static bool bch2_trans_locked(struct btree_trans *trans)
{
struct btree_path *path;
unsigned i;
trans_for_each_path(trans, path, i)
if (path->nodes_locked)
return true;
return false;
}
void bch2_trans_verify_locks(struct btree_trans *trans) void bch2_trans_verify_locks(struct btree_trans *trans)
{ {
struct btree_path *path; struct btree_path *path;
......
...@@ -469,6 +469,8 @@ struct btree_trans { ...@@ -469,6 +469,8 @@ struct btree_trans {
u8 lock_must_abort; u8 lock_must_abort;
bool lock_may_not_fail:1; bool lock_may_not_fail:1;
bool srcu_held:1; bool srcu_held:1;
bool locked:1;
bool write_locked:1;
bool used_mempool:1; bool used_mempool:1;
bool in_traverse_all:1; bool in_traverse_all:1;
bool paths_sorted:1; bool paths_sorted:1;
...@@ -476,13 +478,13 @@ struct btree_trans { ...@@ -476,13 +478,13 @@ struct btree_trans {
bool journal_transaction_names:1; bool journal_transaction_names:1;
bool journal_replay_not_finished:1; bool journal_replay_not_finished:1;
bool notrace_relock_fail:1; bool notrace_relock_fail:1;
bool write_locked:1;
enum bch_errcode restarted:16; enum bch_errcode restarted:16;
u32 restart_count; u32 restart_count;
u64 last_begin_time; u64 last_begin_time;
unsigned long last_begin_ip; unsigned long last_begin_ip;
unsigned long last_restarted_ip; unsigned long last_restarted_ip;
unsigned long last_unlock_ip;
unsigned long srcu_lock_time; unsigned long srcu_lock_time;
const char *fn; const char *fn;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment