bcachefs: Also show when blocked on write locks
This consolidates some of the btree node lock path, so that when we're blocked taking a write lock on a node it shows up in bch2_btree_trans_to_text(), along with intent and read locks. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
parent
8be1aff009
commit
c7ce27328b
@ -150,7 +150,7 @@ void __bch2_btree_node_lock_write(struct btree_trans *trans, struct btree *b)
|
||||
else
|
||||
this_cpu_sub(*b->c.lock.readers, readers);
|
||||
|
||||
btree_node_lock_type(trans->c, b, SIX_LOCK_write);
|
||||
six_lock_write(&b->c.lock, NULL, NULL);
|
||||
|
||||
if (!b->c.lock.readers)
|
||||
atomic64_add(__SIX_VAL(read_lock, readers),
|
||||
@ -289,9 +289,7 @@ bool __bch2_btree_node_lock(struct btree_trans *trans,
|
||||
unsigned long ip)
|
||||
{
|
||||
struct btree_path *linked, *deadlock_path = NULL;
|
||||
u64 start_time = local_clock();
|
||||
unsigned reason = 9;
|
||||
bool ret;
|
||||
|
||||
/* Check if it's safe to block: */
|
||||
trans_for_each_path(trans, linked) {
|
||||
@ -368,23 +366,8 @@ bool __bch2_btree_node_lock(struct btree_trans *trans,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (six_trylock_type(&b->c.lock, type))
|
||||
return true;
|
||||
|
||||
trans->locking_path_idx = path->idx;
|
||||
trans->locking_pos = pos;
|
||||
trans->locking_btree_id = path->btree_id;
|
||||
trans->locking_level = level;
|
||||
trans->locking = b;
|
||||
|
||||
ret = six_lock_type(&b->c.lock, type, should_sleep_fn, p) == 0;
|
||||
|
||||
trans->locking = NULL;
|
||||
|
||||
if (ret)
|
||||
bch2_time_stats_update(&trans->c->times[lock_to_time_stat(type)],
|
||||
start_time);
|
||||
return ret;
|
||||
return btree_node_lock_type(trans, path, b, pos, level,
|
||||
type, should_sleep_fn, p);
|
||||
}
|
||||
|
||||
/* Btree iterator locking: */
|
||||
@ -3191,6 +3174,7 @@ void bch2_btree_trans_to_text(struct printbuf *out, struct bch_fs *c)
|
||||
struct btree_trans *trans;
|
||||
struct btree_path *path;
|
||||
struct btree *b;
|
||||
static char lock_types[] = { 'r', 'i', 'w' };
|
||||
unsigned l;
|
||||
|
||||
mutex_lock(&c->btree_trans_lock);
|
||||
@ -3227,10 +3211,11 @@ void bch2_btree_trans_to_text(struct printbuf *out, struct bch_fs *c)
|
||||
b = READ_ONCE(trans->locking);
|
||||
if (b) {
|
||||
path = &trans->paths[trans->locking_path_idx];
|
||||
pr_buf(out, " locking path %u %c l=%u %s:",
|
||||
pr_buf(out, " locking path %u %c l=%u %c %s:",
|
||||
trans->locking_path_idx,
|
||||
path->cached ? 'c' : 'b',
|
||||
trans->locking_level,
|
||||
lock_types[trans->locking_lock_type],
|
||||
bch2_btree_ids[trans->locking_btree_id]);
|
||||
bch2_bpos_to_text(out, trans->locking_pos);
|
||||
|
||||
|
@ -127,23 +127,35 @@ static inline enum bch_time_stats lock_to_time_stat(enum six_lock_type type)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* wrapper around six locks that just traces lock contended time
|
||||
*/
|
||||
static inline void __btree_node_lock_type(struct bch_fs *c, struct btree *b,
|
||||
enum six_lock_type type)
|
||||
static inline bool btree_node_lock_type(struct btree_trans *trans,
|
||||
struct btree_path *path,
|
||||
struct btree *b,
|
||||
struct bpos pos, unsigned level,
|
||||
enum six_lock_type type,
|
||||
six_lock_should_sleep_fn should_sleep_fn, void *p)
|
||||
{
|
||||
u64 start_time = local_clock();
|
||||
struct bch_fs *c = trans->c;
|
||||
u64 start_time;
|
||||
bool ret;
|
||||
|
||||
six_lock_type(&b->c.lock, type, NULL, NULL);
|
||||
bch2_time_stats_update(&c->times[lock_to_time_stat(type)], start_time);
|
||||
}
|
||||
if (six_trylock_type(&b->c.lock, type))
|
||||
return true;
|
||||
|
||||
static inline void btree_node_lock_type(struct bch_fs *c, struct btree *b,
|
||||
enum six_lock_type type)
|
||||
{
|
||||
if (!six_trylock_type(&b->c.lock, type))
|
||||
__btree_node_lock_type(c, b, type);
|
||||
start_time = local_clock();
|
||||
|
||||
trans->locking_path_idx = path->idx;
|
||||
trans->locking_pos = pos;
|
||||
trans->locking_btree_id = path->btree_id;
|
||||
trans->locking_level = level;
|
||||
trans->locking_lock_type = type;
|
||||
trans->locking = b;
|
||||
ret = six_lock_type(&b->c.lock, type, should_sleep_fn, p) == 0;
|
||||
trans->locking = NULL;
|
||||
|
||||
if (ret)
|
||||
bch2_time_stats_update(&c->times[lock_to_time_stat(type)], start_time);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -383,6 +383,7 @@ struct btree_trans {
|
||||
struct bpos locking_pos;
|
||||
u8 locking_btree_id;
|
||||
u8 locking_level;
|
||||
u8 locking_lock_type;
|
||||
pid_t pid;
|
||||
int srcu_idx;
|
||||
|
||||
|
@ -607,8 +607,8 @@ err:
|
||||
* we're in journal error state:
|
||||
*/
|
||||
|
||||
btree_node_lock_type(c, b, SIX_LOCK_intent);
|
||||
btree_node_lock_type(c, b, SIX_LOCK_write);
|
||||
six_lock_intent(&b->c.lock, NULL, NULL);
|
||||
six_lock_write(&b->c.lock, NULL, NULL);
|
||||
mutex_lock(&c->btree_interior_update_lock);
|
||||
|
||||
list_del(&as->write_blocked_list);
|
||||
@ -662,7 +662,7 @@ err:
|
||||
for (i = 0; i < as->nr_new_nodes; i++) {
|
||||
b = as->new_nodes[i];
|
||||
|
||||
btree_node_lock_type(c, b, SIX_LOCK_read);
|
||||
six_lock_read(&b->c.lock, NULL, NULL);
|
||||
btree_node_write_if_need(c, b, SIX_LOCK_read);
|
||||
six_unlock_read(&b->c.lock);
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ static int __btree_node_flush(struct journal *j, struct journal_entry_pin *pin,
|
||||
struct btree_write *w = container_of(pin, struct btree_write, journal);
|
||||
struct btree *b = container_of(w, struct btree, writes[i]);
|
||||
|
||||
btree_node_lock_type(c, b, SIX_LOCK_read);
|
||||
six_lock_read(&b->c.lock, NULL, NULL);
|
||||
bch2_btree_node_write_cond(c, b,
|
||||
(btree_current_write(b) == w && w->journal.seq == seq));
|
||||
six_unlock_read(&b->c.lock);
|
||||
@ -626,8 +626,10 @@ static inline int trans_lock_write(struct btree_trans *trans)
|
||||
if (have_conflicting_read_lock(trans, i->path))
|
||||
goto fail;
|
||||
|
||||
__btree_node_lock_type(trans->c, insert_l(i)->b,
|
||||
SIX_LOCK_write);
|
||||
btree_node_lock_type(trans, i->path,
|
||||
insert_l(i)->b,
|
||||
i->path->pos, i->level,
|
||||
SIX_LOCK_write, NULL, NULL);
|
||||
}
|
||||
|
||||
bch2_btree_node_prep_for_write(trans, i->path, insert_l(i)->b);
|
||||
|
Loading…
x
Reference in New Issue
Block a user