summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-04-16 21:42:05 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:08:20 +0300
commit53beb841623bcdb1fe619efe5f2c34ca3af08c78 (patch)
tree6f25c64d6e0051884cce244ce9a82e860a0f3753
parentc6dd04f8f5644d92361bb2d6e47fa9b4d5af6d79 (diff)
downloadlinux-53beb841623bcdb1fe619efe5f2c34ca3af08c78.tar.xz
bcachefs: lockdep fix when going rw from bch2_alloc_write()
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/alloc_background.c35
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;
}