bcachefs: Also show when blocked on write locks
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 16 Feb 2022 03:28:37 +0000 (22:28 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:23 +0000 (17:09 -0400)
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>
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_locking.h
fs/bcachefs/btree_types.h
fs/bcachefs/btree_update_interior.c
fs/bcachefs/btree_update_leaf.c

index c56f9e1..6c1fbe3 100644 (file)
@@ -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);
 
index d056891..4a87fa6 100644 (file)
@@ -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;
 }
 
 /*
index 0afade4..7e5b70f 100644 (file)
@@ -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;
 
index 7d5efb3..07bece9 100644 (file)
@@ -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);
        }
index dc03399..bde4bb2 100644 (file)
@@ -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);