diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-04-16 14:42:05 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2019-04-16 15:14:45 -0400 |
commit | 08b175c6a2a010e92d198398fd5709033442a3ae (patch) | |
tree | eeec18344cead651c858bacf5fd305bfc2abb138 | |
parent | 6dde14ace9452461e2e6868535d15ce3a7e37d0a (diff) |
bcachefs: lockdep fix when going rw from bch2_alloc_write()
-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 eb287ecbbadb..ee0c7e9e8246 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -410,21 +410,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); @@ -434,6 +434,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) @@ -443,15 +454,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; } |