Commit 0c0cbfdb authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: bch2_dir_emit() - drop_locks_do() conversion

Add a new helper that calls dir_emit() and updates ctx->pos on success;
this lets us convert bch2_readdir() to drop_locks_do().
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 65bd4423
...@@ -528,16 +528,26 @@ int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir) ...@@ -528,16 +528,26 @@ int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
bch2_empty_dir_snapshot(trans, dir.inum, dir.subvol, snapshot); bch2_empty_dir_snapshot(trans, dir.inum, dir.subvol, snapshot);
} }
static int bch2_dir_emit(struct dir_context *ctx, struct bkey_s_c_dirent d, subvol_inum target)
{
struct qstr name = bch2_dirent_get_name(d);
bool ret = dir_emit(ctx, name.name,
name.len,
target.inum,
vfs_d_type(d.v->d_type));
if (ret)
ctx->pos = d.k->p.offset + 1;
return ret;
}
int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx) int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
{ {
struct btree_trans *trans = bch2_trans_get(c); struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_s_c_dirent dirent;
subvol_inum target; subvol_inum target;
u32 snapshot; u32 snapshot;
struct bkey_buf sk; struct bkey_buf sk;
struct qstr name;
int ret; int ret;
bch2_bkey_buf_init(&sk); bch2_bkey_buf_init(&sk);
...@@ -554,7 +564,9 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx) ...@@ -554,7 +564,9 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
if (k.k->type != KEY_TYPE_dirent) if (k.k->type != KEY_TYPE_dirent)
continue; continue;
dirent = bkey_s_c_to_dirent(k); /* dir_emit() can fault and block: */
bch2_bkey_buf_reassemble(&sk, c, k);
struct bkey_s_c_dirent dirent = bkey_i_to_s_c_dirent(sk.k);
ret = bch2_dirent_read_target(trans, inum, dirent, &target); ret = bch2_dirent_read_target(trans, inum, dirent, &target);
if (ret < 0) if (ret < 0)
...@@ -562,28 +574,22 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx) ...@@ -562,28 +574,22 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
if (ret) if (ret)
continue; continue;
/* 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);
name = bch2_dirent_get_name(dirent);
ctx->pos = dirent.k->p.offset;
if (!dir_emit(ctx, name.name,
name.len,
target.inum,
vfs_d_type(dirent.v->d_type)))
break;
ctx->pos = dirent.k->p.offset + 1;
/* /*
* read_target looks up subvolumes, we can overflow paths if the * read_target looks up subvolumes, we can overflow paths if the
* directory has many subvolumes in it * directory has many subvolumes in it
*
* XXX: btree_trans_too_many_iters() is something we'd like to
* get rid of, and there's no good reason to be using it here
* except that we don't yet have a for_each_btree_key() helper
* that does subvolume_get_snapshot().
*/ */
ret = btree_trans_too_many_iters(trans); ret = drop_locks_do(trans,
if (ret) bch2_dir_emit(ctx, dirent, target)) ?:
btree_trans_too_many_iters(trans);
if (ret) {
ret = ret < 0 ? ret : 0;
break; break;
}
} }
bch2_trans_iter_exit(trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment