diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-04-16 14:42:05 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:20 -0400 |
commit | 53beb841623bcdb1fe619efe5f2c34ca3af08c78 (patch) | |
tree | 6f25c64d6e0051884cce244ce9a82e860a0f3753 /fs | |
parent | c6dd04f8f5644d92361bb2d6e47fa9b4d5af6d79 (diff) |
bcachefs: lockdep fix when going rw from bch2_alloc_write()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/alloc_background.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c index 5c8cebc443d1..c254c08af9d1 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -411,21 +411,21 @@ static int __bch2_alloc_write_key(struct btree_trans *trans, struct bch_dev *ca, int bch2_alloc_write(struct bch_fs *c, unsigned flags, bool *wrote) { + struct btree_trans trans; + struct btree_iter *iter; + struct bucket_array *buckets; struct bch_dev *ca; unsigned i; + size_t b; int ret = 0; - for_each_rw_member(ca, c, i) { - struct btree_trans trans; - struct btree_iter *iter; - struct bucket_array *buckets; - size_t b; - - bch2_trans_init(&trans, c); + bch2_trans_init(&trans, c); - iter = bch2_trans_get_iter(&trans, BTREE_ID_ALLOC, POS_MIN, - BTREE_ITER_SLOTS|BTREE_ITER_INTENT); + iter = bch2_trans_get_iter(&trans, BTREE_ID_ALLOC, POS_MIN, + BTREE_ITER_SLOTS|BTREE_ITER_INTENT); + for_each_rw_member(ca, c, i) { +relock: down_read(&ca->bucket_lock); buckets = bucket_array(ca); @@ -435,6 +435,17 @@ int bch2_alloc_write(struct bch_fs *c, unsigned flags, bool *wrote) if (!buckets->b[b].mark.dirty) continue; + if ((flags & BTREE_INSERT_LAZY_RW) && + percpu_ref_is_zero(&c->writes)) { + up_read(&ca->bucket_lock); + bch2_trans_unlock(&trans); + + ret = bch2_fs_read_write_early(c); + if (ret) + goto out; + goto relock; + } + ret = __bch2_alloc_write_key(&trans, ca, b, iter, flags); if (ret) @@ -444,15 +455,15 @@ int bch2_alloc_write(struct bch_fs *c, unsigned flags, bool *wrote) *wrote = true; } up_read(&ca->bucket_lock); - - bch2_trans_exit(&trans); - +out: if (ret) { percpu_ref_put(&ca->io_ref); break; } } + bch2_trans_exit(&trans); + return ret; } |