summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-06-21 06:00:04 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-06-21 06:00:44 -0400
commiteac40840098bfbb5fa1711f6bbce71b27bbccb89 (patch)
tree1007072e80a7ee64ef407adcc8b63f1deb9a36b5
parent15571cfa8c55c1f011b8f3e9947a4d8fa97de9dd (diff)
bcachefs: Fix lockdep splat in bch2_readdir
dir_emit() can fault (taking mmap_lock); thus we can't be holding btree locks. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/dirent.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c
index 1544fc56974f..610dd7425fb4 100644
--- a/fs/bcachefs/dirent.c
+++ b/fs/bcachefs/dirent.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcachefs.h"
+#include "bkey_buf.h"
#include "bkey_methods.h"
#include "btree_update.h"
#include "extents.h"
@@ -504,8 +505,10 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
struct bkey_s_c_dirent dirent;
subvol_inum target;
u32 snapshot;
+ struct bkey_buf sk;
int ret;
+ bch2_bkey_buf_init(&sk);
bch2_trans_init(&trans, c, 0, 0);
retry:
bch2_trans_begin(&trans);
@@ -528,10 +531,11 @@ retry:
if (ret)
continue;
- /*
- * XXX: dir_emit() can fault and block, while we're holding
- * locks
- */
+ /* dir_emit() can fault and block: */
+ bch2_bkey_buf_reassemble(&sk, c, k);
+ dirent = bkey_i_to_s_c_dirent(sk.k);
+ bch2_trans_unlock(&trans);
+
ctx->pos = dirent.k->p.offset;
if (!dir_emit(ctx, dirent.v->d_name,
bch2_dirent_name_bytes(dirent),
@@ -554,6 +558,7 @@ err:
goto retry;
bch2_trans_exit(&trans);
+ bch2_bkey_buf_exit(&sk, c);
return ret;
}