summaryrefslogtreecommitdiff
path: root/fs/bcachefs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-02-16 06:28:37 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:23 +0300
commitc7ce27328ba133d6cce76a4df7667088009d4543 (patch)
treea99dceac65256ce31660eb213bbabee26ad810a4 /fs/bcachefs
parent8be1aff0092a1f747973bf978ab8411b257af461 (diff)
downloadlinux-c7ce27328ba133d6cce76a4df7667088009d4543.tar.xz
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>
Diffstat (limited to 'fs/bcachefs')
-rw-r--r--fs/bcachefs/btree_iter.c27
-rw-r--r--fs/bcachefs/btree_locking.h46
-rw-r--r--fs/bcachefs/btree_types.h1
-rw-r--r--fs/bcachefs/btree_update_interior.c6
-rw-r--r--fs/bcachefs/btree_update_leaf.c8
5 files changed, 44 insertions, 44 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index c56f9e101b42..6c1fbe3e3bda 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -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);
diff --git a/fs/bcachefs/btree_locking.h b/fs/bcachefs/btree_locking.h
index d05689180c63..4a87fa625d7a 100644
--- a/fs/bcachefs/btree_locking.h
+++ b/fs/bcachefs/btree_locking.h
@@ -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)
-{
- u64 start_time = local_clock();
-
- six_lock_type(&b->c.lock, type, NULL, NULL);
- bch2_time_stats_update(&c->times[lock_to_time_stat(type)], start_time);
-}
-
-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);
+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)
+{
+ struct bch_fs *c = trans->c;
+ u64 start_time;
+ bool ret;
+
+ if (six_trylock_type(&b->c.lock, type))
+ return true;
+
+ 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;
}
/*
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index 0afade4f61f4..7e5b70f60444 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -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;
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index 7d5efb32b082..07bece908691 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -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);
}
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c
index dc033991a4ec..bde4bb2b7fcc 100644
--- a/fs/bcachefs/btree_update_leaf.c
+++ b/fs/bcachefs/btree_update_leaf.c
@@ -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);