Skip to content

Commit 677bdb7

Browse files
alanskindKent Overstreet
authored andcommitted
bcachefs: Fix deadlock
This fixes two deadlocks: 1.pcpu_alloc_mutex involved one as pointed by syzbot[1] 2.recursion deadlock. The root cause is that we hold the bc lock during alloc_percpu, fix it by following the pattern used by __btree_node_mem_alloc(). [1] https://lore.kernel.org/all/66f97d9a.050a0220.6bad9.001d.GAE@google.com/T/ Reported-by: syzbot+fe63f377148a6371a9db@syzkaller.appspotmail.com Tested-by: syzbot+fe63f377148a6371a9db@syzkaller.appspotmail.com Signed-off-by: Alan Huang <mmpgouride@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 7909d1f commit 677bdb7

File tree

6 files changed

+17
-13
lines changed

6 files changed

+17
-13
lines changed

fs/bcachefs/btree_cache.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ struct btree *__bch2_btree_node_mem_alloc(struct bch_fs *c)
203203
return NULL;
204204
}
205205

206-
bch2_btree_lock_init(&b->c, 0);
206+
bch2_btree_lock_init(&b->c, 0, GFP_KERNEL);
207207

208208
__bch2_btree_node_to_freelist(bc, b);
209209
return b;
@@ -795,17 +795,18 @@ struct btree *bch2_btree_node_mem_alloc(struct btree_trans *trans, bool pcpu_rea
795795
}
796796

797797
b = __btree_node_mem_alloc(c, GFP_NOWAIT|__GFP_NOWARN);
798-
if (!b) {
798+
if (b) {
799+
bch2_btree_lock_init(&b->c, pcpu_read_locks ? SIX_LOCK_INIT_PCPU : 0, GFP_NOWAIT);
800+
} else {
799801
mutex_unlock(&bc->lock);
800802
bch2_trans_unlock(trans);
801803
b = __btree_node_mem_alloc(c, GFP_KERNEL);
802804
if (!b)
803805
goto err;
806+
bch2_btree_lock_init(&b->c, pcpu_read_locks ? SIX_LOCK_INIT_PCPU : 0, GFP_KERNEL);
804807
mutex_lock(&bc->lock);
805808
}
806809

807-
bch2_btree_lock_init(&b->c, pcpu_read_locks ? SIX_LOCK_INIT_PCPU : 0);
808-
809810
BUG_ON(!six_trylock_intent(&b->c.lock));
810811
BUG_ON(!six_trylock_write(&b->c.lock));
811812

fs/bcachefs/btree_key_cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ bkey_cached_alloc(struct btree_trans *trans, struct btree_path *path, unsigned k
156156
}
157157

158158
if (ck) {
159-
bch2_btree_lock_init(&ck->c, pcpu_readers ? SIX_LOCK_INIT_PCPU : 0);
159+
bch2_btree_lock_init(&ck->c, pcpu_readers ? SIX_LOCK_INIT_PCPU : 0, GFP_KERNEL);
160160
ck->c.cached = true;
161161
goto lock;
162162
}

fs/bcachefs/btree_locking.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
static struct lock_class_key bch2_btree_node_lock_key;
88

99
void bch2_btree_lock_init(struct btree_bkey_cached_common *b,
10-
enum six_lock_init_flags flags)
10+
enum six_lock_init_flags flags,
11+
gfp_t gfp)
1112
{
12-
__six_lock_init(&b->lock, "b->c.lock", &bch2_btree_node_lock_key, flags);
13+
__six_lock_init(&b->lock, "b->c.lock", &bch2_btree_node_lock_key, flags, gfp);
1314
lockdep_set_notrack_class(&b->lock);
1415
}
1516

fs/bcachefs/btree_locking.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include "btree_iter.h"
1414
#include "six.h"
1515

16-
void bch2_btree_lock_init(struct btree_bkey_cached_common *, enum six_lock_init_flags);
16+
void bch2_btree_lock_init(struct btree_bkey_cached_common *, enum six_lock_init_flags, gfp_t gfp);
1717

1818
void bch2_trans_unlock_noassert(struct btree_trans *);
1919
void bch2_trans_unlock_write(struct btree_trans *);

fs/bcachefs/six.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,8 @@ void six_lock_exit(struct six_lock *lock)
850850
EXPORT_SYMBOL_GPL(six_lock_exit);
851851

852852
void __six_lock_init(struct six_lock *lock, const char *name,
853-
struct lock_class_key *key, enum six_lock_init_flags flags)
853+
struct lock_class_key *key, enum six_lock_init_flags flags,
854+
gfp_t gfp)
854855
{
855856
atomic_set(&lock->state, 0);
856857
raw_spin_lock_init(&lock->wait_lock);
@@ -873,7 +874,7 @@ void __six_lock_init(struct six_lock *lock, const char *name,
873874
* failure if they wish by checking lock->readers, but generally
874875
* will not want to treat it as an error.
875876
*/
876-
lock->readers = alloc_percpu(unsigned);
877+
lock->readers = alloc_percpu_gfp(unsigned, gfp);
877878
}
878879
#endif
879880
}

fs/bcachefs/six.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,18 +164,19 @@ enum six_lock_init_flags {
164164
};
165165

166166
void __six_lock_init(struct six_lock *lock, const char *name,
167-
struct lock_class_key *key, enum six_lock_init_flags flags);
167+
struct lock_class_key *key, enum six_lock_init_flags flags,
168+
gfp_t gfp);
168169

169170
/**
170171
* six_lock_init - initialize a six lock
171172
* @lock: lock to initialize
172173
* @flags: optional flags, i.e. SIX_LOCK_INIT_PCPU
173174
*/
174-
#define six_lock_init(lock, flags) \
175+
#define six_lock_init(lock, flags, gfp) \
175176
do { \
176177
static struct lock_class_key __key; \
177178
\
178-
__six_lock_init((lock), #lock, &__key, flags); \
179+
__six_lock_init((lock), #lock, &__key, flags, gfp); \
179180
} while (0)
180181

181182
/**

0 commit comments

Comments
 (0)