Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bcachefs; Fix deadlock in bch2_btree_update_start()

BCH_TRANS_COMMIT_journal_reclaim with watermark != BCH_WATERMARK_reclaim
means nonblocking, and we need the journal_res_get() in
btree_update_start() to respect that.

In a future refactoring we'll be deleting
BCH_TRANS_COMMIT_journal_reclaim and replacing it with an explicit
BCH_TRANS_COMMIT_nonblocking.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>

+9 -4
+9 -4
fs/bcachefs/btree_update_interior.c
··· 1067 1067 flags &= ~BCH_WATERMARK_MASK; 1068 1068 flags |= watermark; 1069 1069 1070 - if (!(flags & BCH_TRANS_COMMIT_journal_reclaim) && 1071 - watermark < c->journal.watermark) { 1070 + if (watermark < c->journal.watermark) { 1072 1071 struct journal_res res = { 0 }; 1072 + unsigned journal_flags = watermark|JOURNAL_RES_GET_CHECK; 1073 + 1074 + if ((flags & BCH_TRANS_COMMIT_journal_reclaim) && 1075 + watermark != BCH_WATERMARK_reclaim) 1076 + journal_flags |= JOURNAL_RES_GET_NONBLOCK; 1073 1077 1074 1078 ret = drop_locks_do(trans, 1075 - bch2_journal_res_get(&c->journal, &res, 1, 1076 - watermark|JOURNAL_RES_GET_CHECK)); 1079 + bch2_journal_res_get(&c->journal, &res, 1, journal_flags)); 1080 + if (bch2_err_matches(ret, BCH_ERR_operation_blocked)) 1081 + ret = -BCH_ERR_journal_reclaim_would_deadlock; 1077 1082 if (ret) 1078 1083 return ERR_PTR(ret); 1079 1084 }