Skip to content

Commit 61198e6

Browse files
alanskindKent Overstreet
authored andcommitted
bcachefs: Fix self deadlock
Before invoking bch2_accounting_mem_mod_locked in bch2_gc_accounting_done, we already write locked mark_lock, in bch2_accounting_mem_insert, we lock mark_lock again. Signed-off-by: Alan Huang <[email protected]> Signed-off-by: Kent Overstreet <[email protected]>
1 parent 19b22d0 commit 61198e6

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

fs/bcachefs/disk_accounting.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,19 @@ int bch2_accounting_mem_insert(struct bch_fs *c, struct bkey_s_c_accounting a,
376376
return ret;
377377
}
378378

379+
int bch2_accounting_mem_insert_locked(struct bch_fs *c, struct bkey_s_c_accounting a,
380+
enum bch_accounting_mode mode)
381+
{
382+
struct bch_replicas_padded r;
383+
384+
if (mode != BCH_ACCOUNTING_read &&
385+
accounting_to_replicas(&r.e, a.k->p) &&
386+
!bch2_replicas_marked_locked(c, &r.e))
387+
return -BCH_ERR_btree_insert_need_mark_replicas;
388+
389+
return __bch2_accounting_mem_insert(c, a);
390+
}
391+
379392
static bool accounting_mem_entry_is_zero(struct accounting_mem_entry *e)
380393
{
381394
for (unsigned i = 0; i < e->nr_counters; i++)
@@ -583,7 +596,7 @@ int bch2_gc_accounting_done(struct bch_fs *c)
583596
accounting_key_init(&k_i.k, &acc_k, src_v, nr);
584597
bch2_accounting_mem_mod_locked(trans,
585598
bkey_i_to_s_c_accounting(&k_i.k),
586-
BCH_ACCOUNTING_normal);
599+
BCH_ACCOUNTING_normal, true);
587600

588601
preempt_disable();
589602
struct bch_fs_usage_base *dst = this_cpu_ptr(c->usage);
@@ -612,7 +625,7 @@ static int accounting_read_key(struct btree_trans *trans, struct bkey_s_c k)
612625

613626
percpu_down_read(&c->mark_lock);
614627
int ret = bch2_accounting_mem_mod_locked(trans, bkey_s_c_to_accounting(k),
615-
BCH_ACCOUNTING_read);
628+
BCH_ACCOUNTING_read, false);
616629
percpu_up_read(&c->mark_lock);
617630
return ret;
618631
}

fs/bcachefs/disk_accounting.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ enum bch_accounting_mode {
136136
};
137137

138138
int bch2_accounting_mem_insert(struct bch_fs *, struct bkey_s_c_accounting, enum bch_accounting_mode);
139+
int bch2_accounting_mem_insert_locked(struct bch_fs *, struct bkey_s_c_accounting, enum bch_accounting_mode);
139140
void bch2_accounting_mem_gc(struct bch_fs *);
140141

141142
static inline bool bch2_accounting_is_mem(struct disk_accounting_pos acc)
@@ -150,7 +151,8 @@ static inline bool bch2_accounting_is_mem(struct disk_accounting_pos acc)
150151
*/
151152
static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans,
152153
struct bkey_s_c_accounting a,
153-
enum bch_accounting_mode mode)
154+
enum bch_accounting_mode mode,
155+
bool write_locked)
154156
{
155157
struct bch_fs *c = trans->c;
156158
struct bch_accounting_mem *acc = &c->accounting;
@@ -189,7 +191,11 @@ static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans,
189191

190192
while ((idx = eytzinger0_find(acc->k.data, acc->k.nr, sizeof(acc->k.data[0]),
191193
accounting_pos_cmp, &a.k->p)) >= acc->k.nr) {
192-
int ret = bch2_accounting_mem_insert(c, a, mode);
194+
int ret = 0;
195+
if (unlikely(write_locked))
196+
ret = bch2_accounting_mem_insert_locked(c, a, mode);
197+
else
198+
ret = bch2_accounting_mem_insert(c, a, mode);
193199
if (ret)
194200
return ret;
195201
}
@@ -206,7 +212,7 @@ static inline int bch2_accounting_mem_mod_locked(struct btree_trans *trans,
206212
static inline int bch2_accounting_mem_add(struct btree_trans *trans, struct bkey_s_c_accounting a, bool gc)
207213
{
208214
percpu_down_read(&trans->c->mark_lock);
209-
int ret = bch2_accounting_mem_mod_locked(trans, a, gc ? BCH_ACCOUNTING_gc : BCH_ACCOUNTING_normal);
215+
int ret = bch2_accounting_mem_mod_locked(trans, a, gc ? BCH_ACCOUNTING_gc : BCH_ACCOUNTING_normal, false);
210216
percpu_up_read(&trans->c->mark_lock);
211217
return ret;
212218
}
@@ -259,7 +265,7 @@ static inline int bch2_accounting_trans_commit_hook(struct btree_trans *trans,
259265
EBUG_ON(bversion_zero(a->k.bversion));
260266

261267
return likely(!(commit_flags & BCH_TRANS_COMMIT_skip_accounting_apply))
262-
? bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), BCH_ACCOUNTING_normal)
268+
? bch2_accounting_mem_mod_locked(trans, accounting_i_to_s_c(a), BCH_ACCOUNTING_normal, false)
263269
: 0;
264270
}
265271

@@ -271,7 +277,7 @@ static inline void bch2_accounting_trans_commit_revert(struct btree_trans *trans
271277
struct bkey_s_accounting a = accounting_i_to_s(a_i);
272278

273279
bch2_accounting_neg(a);
274-
bch2_accounting_mem_mod_locked(trans, a.c, BCH_ACCOUNTING_normal);
280+
bch2_accounting_mem_mod_locked(trans, a.c, BCH_ACCOUNTING_normal, false);
275281
bch2_accounting_neg(a);
276282
}
277283
}

0 commit comments

Comments
 (0)