mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
bcachefs: bch2_inum_to_path()
Add a function for walking backpointers to find a path from a given inode number, and convert various error messages to use it. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
428a2c2d6b
commit
2ab8d31989
@ -116,6 +116,7 @@
|
||||
x(ENOENT, ENOENT_dirent_doesnt_match_inode) \
|
||||
x(ENOENT, ENOENT_dev_not_found) \
|
||||
x(ENOENT, ENOENT_dev_idx_not_found) \
|
||||
x(ENOENT, ENOENT_inode_no_backpointer) \
|
||||
x(ENOTEMPTY, ENOTEMPTY_dir_not_empty) \
|
||||
x(ENOTEMPTY, ENOTEMPTY_subvol_not_empty) \
|
||||
x(EEXIST, EEXIST_str_hash_set) \
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "btree_cache.h"
|
||||
#include "btree_iter.h"
|
||||
#include "error.h"
|
||||
#include "fs-common.h"
|
||||
#include "journal.h"
|
||||
#include "recovery_passes.h"
|
||||
#include "super.h"
|
||||
@ -515,3 +516,36 @@ void bch2_flush_fsck_errs(struct bch_fs *c)
|
||||
|
||||
mutex_unlock(&c->fsck_error_msgs_lock);
|
||||
}
|
||||
|
||||
int bch2_inum_err_msg_trans(struct btree_trans *trans, struct printbuf *out, subvol_inum inum)
|
||||
{
|
||||
u32 restart_count = trans->restart_count;
|
||||
int ret = 0;
|
||||
|
||||
/* XXX: we don't yet attempt to print paths when we don't know the subvol */
|
||||
if (inum.subvol)
|
||||
ret = lockrestart_do(trans, bch2_inum_to_path(trans, inum, out));
|
||||
if (!inum.subvol || ret)
|
||||
prt_printf(out, "inum %llu:%llu", inum.subvol, inum.inum);
|
||||
|
||||
return trans_was_restarted(trans, restart_count);
|
||||
}
|
||||
|
||||
int bch2_inum_offset_err_msg_trans(struct btree_trans *trans, struct printbuf *out,
|
||||
subvol_inum inum, u64 offset)
|
||||
{
|
||||
int ret = bch2_inum_err_msg_trans(trans, out, inum);
|
||||
prt_printf(out, " offset %llu: ", offset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bch2_inum_err_msg(struct bch_fs *c, struct printbuf *out, subvol_inum inum)
|
||||
{
|
||||
bch2_trans_run(c, bch2_inum_err_msg_trans(trans, out, inum));
|
||||
}
|
||||
|
||||
void bch2_inum_offset_err_msg(struct bch_fs *c, struct printbuf *out,
|
||||
subvol_inum inum, u64 offset)
|
||||
{
|
||||
bch2_trans_run(c, bch2_inum_offset_err_msg_trans(trans, out, inum, offset));
|
||||
}
|
||||
|
@ -238,4 +238,10 @@ void bch2_io_error(struct bch_dev *, enum bch_member_error_type);
|
||||
_ret; \
|
||||
})
|
||||
|
||||
int bch2_inum_err_msg_trans(struct btree_trans *, struct printbuf *, subvol_inum);
|
||||
int bch2_inum_offset_err_msg_trans(struct btree_trans *, struct printbuf *, subvol_inum, u64);
|
||||
|
||||
void bch2_inum_err_msg(struct bch_fs *, struct printbuf *, subvol_inum);
|
||||
void bch2_inum_offset_err_msg(struct bch_fs *, struct printbuf *, subvol_inum, u64);
|
||||
|
||||
#endif /* _BCACHEFS_ERROR_H */
|
||||
|
@ -548,3 +548,84 @@ int bch2_rename_trans(struct btree_trans *trans,
|
||||
bch2_trans_iter_exit(trans, &src_dir_iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void prt_bytes_reversed(struct printbuf *out, const void *b, unsigned n)
|
||||
{
|
||||
bch2_printbuf_make_room(out, n);
|
||||
|
||||
unsigned can_print = min(n, printbuf_remaining(out));
|
||||
|
||||
b += n;
|
||||
|
||||
for (unsigned i = 0; i < can_print; i++)
|
||||
out->buf[out->pos++] = *((char *) --b);
|
||||
|
||||
printbuf_nul_terminate(out);
|
||||
}
|
||||
|
||||
static inline void reverse_bytes(void *b, size_t n)
|
||||
{
|
||||
char *e = b + n, *s = b;
|
||||
|
||||
while (s < e) {
|
||||
--e;
|
||||
swap(*s, *e);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: we don't yet attempt to print paths when we don't know the subvol */
|
||||
int bch2_inum_to_path(struct btree_trans *trans, subvol_inum inum, struct printbuf *path)
|
||||
{
|
||||
unsigned orig_pos = path->pos;
|
||||
int ret = 0;
|
||||
|
||||
while (!(inum.subvol == BCACHEFS_ROOT_SUBVOL &&
|
||||
inum.inum == BCACHEFS_ROOT_INO)) {
|
||||
struct bch_inode_unpacked inode;
|
||||
ret = bch2_inode_find_by_inum_trans(trans, inum, &inode);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (!inode.bi_dir && !inode.bi_dir_offset) {
|
||||
ret = -BCH_ERR_ENOENT_inode_no_backpointer;
|
||||
goto err;
|
||||
}
|
||||
|
||||
u32 snapshot;
|
||||
ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
struct btree_iter d_iter;
|
||||
struct bkey_s_c_dirent d = bch2_bkey_get_iter_typed(trans, &d_iter,
|
||||
BTREE_ID_dirents, SPOS(inode.bi_dir, inode.bi_dir_offset, snapshot),
|
||||
0, dirent);
|
||||
ret = bkey_err(d.s_c);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
struct qstr dirent_name = bch2_dirent_get_name(d);
|
||||
prt_bytes_reversed(path, dirent_name.name, dirent_name.len);
|
||||
|
||||
prt_char(path, '/');
|
||||
|
||||
if (d.v->d_type == DT_SUBVOL)
|
||||
inum.subvol = le32_to_cpu(d.v->d_parent_subvol);
|
||||
inum.inum = d.k->p.inode;
|
||||
|
||||
bch2_trans_iter_exit(trans, &d_iter);
|
||||
}
|
||||
|
||||
if (orig_pos == path->pos)
|
||||
prt_char(path, '/');
|
||||
|
||||
ret = path->allocation_failure ? -ENOMEM : 0;
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
reverse_bytes(path->buf + orig_pos, path->pos - orig_pos);
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
@ -42,4 +42,6 @@ int bch2_rename_trans(struct btree_trans *,
|
||||
bool bch2_reinherit_attrs(struct bch_inode_unpacked *,
|
||||
struct bch_inode_unpacked *);
|
||||
|
||||
int bch2_inum_to_path(struct btree_trans *, subvol_inum, struct printbuf *);
|
||||
|
||||
#endif /* _BCACHEFS_FS_COMMON_H */
|
||||
|
@ -231,10 +231,12 @@ static void bchfs_read(struct btree_trans *trans,
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
|
||||
if (ret) {
|
||||
bch_err_inum_offset_ratelimited(c,
|
||||
iter.pos.inode,
|
||||
iter.pos.offset << 9,
|
||||
"read error %i from btree lookup", ret);
|
||||
struct printbuf buf = PRINTBUF;
|
||||
bch2_inum_offset_err_msg_trans(trans, &buf, inum, iter.pos.offset << 9);
|
||||
prt_printf(&buf, "read error %i from btree lookup", ret);
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
|
||||
rbio->bio.bi_status = BLK_STS_IOERR;
|
||||
bio_endio(&rbio->bio);
|
||||
}
|
||||
|
@ -212,6 +212,7 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
|
||||
{
|
||||
struct bch_fs *c = trans->c;
|
||||
struct qstr lostfound_str = QSTR("lost+found");
|
||||
struct btree_iter lostfound_iter = { NULL };
|
||||
u64 inum = 0;
|
||||
unsigned d_type = 0;
|
||||
int ret;
|
||||
@ -290,11 +291,16 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
|
||||
* XXX: we could have a nicer log message here if we had a nice way to
|
||||
* walk backpointers to print a path
|
||||
*/
|
||||
bch_notice(c, "creating lost+found in subvol %llu snapshot %u",
|
||||
root_inum.subvol, le32_to_cpu(st.root_snapshot));
|
||||
struct printbuf path = PRINTBUF;
|
||||
ret = bch2_inum_to_path(trans, root_inum, &path);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
bch_notice(c, "creating %s/lost+found in subvol %llu snapshot %u",
|
||||
path.buf, root_inum.subvol, snapshot);
|
||||
printbuf_exit(&path);
|
||||
|
||||
u64 now = bch2_current_time(c);
|
||||
struct btree_iter lostfound_iter = { NULL };
|
||||
u64 cpu = raw_smp_processor_id();
|
||||
|
||||
bch2_inode_init_early(c, lostfound);
|
||||
|
@ -113,11 +113,13 @@ int bch2_extent_fallocate(struct btree_trans *trans,
|
||||
err:
|
||||
if (!ret && sectors_allocated)
|
||||
bch2_increment_clock(c, sectors_allocated, WRITE);
|
||||
if (should_print_err(ret))
|
||||
bch_err_inum_offset_ratelimited(c,
|
||||
inum.inum,
|
||||
iter->pos.offset << 9,
|
||||
"%s(): error: %s", __func__, bch2_err_str(ret));
|
||||
if (should_print_err(ret)) {
|
||||
struct printbuf buf = PRINTBUF;
|
||||
bch2_inum_offset_err_msg_trans(trans, &buf, inum, iter->pos.offset << 9);
|
||||
prt_printf(&buf, "fallocate error: %s", bch2_err_str(ret));
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
}
|
||||
err_noprint:
|
||||
bch2_open_buckets_put(c, &open_buckets);
|
||||
bch2_disk_reservation_put(c, &disk_res);
|
||||
|
@ -322,6 +322,20 @@ static struct promote_op *promote_alloc(struct btree_trans *trans,
|
||||
|
||||
/* Read */
|
||||
|
||||
static int bch2_read_err_msg_trans(struct btree_trans *trans, struct printbuf *out,
|
||||
struct bch_read_bio *rbio, struct bpos read_pos)
|
||||
{
|
||||
return bch2_inum_offset_err_msg_trans(trans, out,
|
||||
(subvol_inum) { rbio->subvol, read_pos.inode },
|
||||
read_pos.offset << 9);
|
||||
}
|
||||
|
||||
static void bch2_read_err_msg(struct bch_fs *c, struct printbuf *out,
|
||||
struct bch_read_bio *rbio, struct bpos read_pos)
|
||||
{
|
||||
bch2_trans_run(c, bch2_read_err_msg_trans(trans, out, rbio, read_pos));
|
||||
}
|
||||
|
||||
#define READ_RETRY_AVOID 1
|
||||
#define READ_RETRY 2
|
||||
#define READ_ERR 3
|
||||
@ -500,6 +514,29 @@ static void bch2_rbio_error(struct bch_read_bio *rbio, int retry,
|
||||
}
|
||||
}
|
||||
|
||||
static void bch2_read_io_err(struct work_struct *work)
|
||||
{
|
||||
struct bch_read_bio *rbio =
|
||||
container_of(work, struct bch_read_bio, work);
|
||||
struct bio *bio = &rbio->bio;
|
||||
struct bch_fs *c = rbio->c;
|
||||
struct bch_dev *ca = rbio->have_ioref ? bch2_dev_have_ref(c, rbio->pick.ptr.dev) : NULL;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
bch2_read_err_msg(c, &buf, rbio, rbio->read_pos);
|
||||
prt_printf(&buf, "data read error: %s", bch2_blk_status_to_str(bio->bi_status));
|
||||
|
||||
if (ca) {
|
||||
bch2_io_error(ca, BCH_MEMBER_ERROR_read);
|
||||
bch_err_ratelimited(ca, "%s", buf.buf);
|
||||
} else {
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
}
|
||||
|
||||
printbuf_exit(&buf);
|
||||
bch2_rbio_error(rbio, READ_RETRY_AVOID, bio->bi_status);
|
||||
}
|
||||
|
||||
static int __bch2_rbio_narrow_crcs(struct btree_trans *trans,
|
||||
struct bch_read_bio *rbio)
|
||||
{
|
||||
@ -563,6 +600,73 @@ static noinline void bch2_rbio_narrow_crcs(struct bch_read_bio *rbio)
|
||||
__bch2_rbio_narrow_crcs(trans, rbio));
|
||||
}
|
||||
|
||||
static void bch2_read_csum_err(struct work_struct *work)
|
||||
{
|
||||
struct bch_read_bio *rbio =
|
||||
container_of(work, struct bch_read_bio, work);
|
||||
struct bch_fs *c = rbio->c;
|
||||
struct bio *src = &rbio->bio;
|
||||
struct bch_extent_crc_unpacked crc = rbio->pick.crc;
|
||||
struct nonce nonce = extent_nonce(rbio->version, crc);
|
||||
struct bch_csum csum = bch2_checksum_bio(c, crc.csum_type, nonce, src);
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
bch2_read_err_msg(c, &buf, rbio, rbio->read_pos);
|
||||
prt_str(&buf, "data ");
|
||||
bch2_csum_err_msg(&buf, crc.csum_type, rbio->pick.crc.csum, csum);
|
||||
|
||||
struct bch_dev *ca = rbio->have_ioref ? bch2_dev_have_ref(c, rbio->pick.ptr.dev) : NULL;
|
||||
if (ca) {
|
||||
bch2_io_error(ca, BCH_MEMBER_ERROR_checksum);
|
||||
bch_err_ratelimited(ca, "%s", buf.buf);
|
||||
} else {
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
}
|
||||
|
||||
bch2_rbio_error(rbio, READ_RETRY_AVOID, BLK_STS_IOERR);
|
||||
printbuf_exit(&buf);
|
||||
}
|
||||
|
||||
static void bch2_read_decompress_err(struct work_struct *work)
|
||||
{
|
||||
struct bch_read_bio *rbio =
|
||||
container_of(work, struct bch_read_bio, work);
|
||||
struct bch_fs *c = rbio->c;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
bch2_read_err_msg(c, &buf, rbio, rbio->read_pos);
|
||||
prt_str(&buf, "decompression error");
|
||||
|
||||
struct bch_dev *ca = rbio->have_ioref ? bch2_dev_have_ref(c, rbio->pick.ptr.dev) : NULL;
|
||||
if (ca)
|
||||
bch_err_ratelimited(ca, "%s", buf.buf);
|
||||
else
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
|
||||
bch2_rbio_error(rbio, READ_ERR, BLK_STS_IOERR);
|
||||
printbuf_exit(&buf);
|
||||
}
|
||||
|
||||
static void bch2_read_decrypt_err(struct work_struct *work)
|
||||
{
|
||||
struct bch_read_bio *rbio =
|
||||
container_of(work, struct bch_read_bio, work);
|
||||
struct bch_fs *c = rbio->c;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
bch2_read_err_msg(c, &buf, rbio, rbio->read_pos);
|
||||
prt_str(&buf, "decrypt error");
|
||||
|
||||
struct bch_dev *ca = rbio->have_ioref ? bch2_dev_have_ref(c, rbio->pick.ptr.dev) : NULL;
|
||||
if (ca)
|
||||
bch_err_ratelimited(ca, "%s", buf.buf);
|
||||
else
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
|
||||
bch2_rbio_error(rbio, READ_ERR, BLK_STS_IOERR);
|
||||
printbuf_exit(&buf);
|
||||
}
|
||||
|
||||
/* Inner part that may run in process context */
|
||||
static void __bch2_read_endio(struct work_struct *work)
|
||||
{
|
||||
@ -669,33 +773,13 @@ static void __bch2_read_endio(struct work_struct *work)
|
||||
goto out;
|
||||
}
|
||||
|
||||
struct printbuf buf = PRINTBUF;
|
||||
buf.atomic++;
|
||||
prt_str(&buf, "data ");
|
||||
bch2_csum_err_msg(&buf, crc.csum_type, rbio->pick.crc.csum, csum);
|
||||
|
||||
struct bch_dev *ca = rbio->have_ioref ? bch2_dev_have_ref(c, rbio->pick.ptr.dev) : NULL;
|
||||
if (ca) {
|
||||
bch_err_inum_offset_ratelimited(ca,
|
||||
rbio->read_pos.inode,
|
||||
rbio->read_pos.offset << 9,
|
||||
"data %s", buf.buf);
|
||||
bch2_io_error(ca, BCH_MEMBER_ERROR_checksum);
|
||||
}
|
||||
printbuf_exit(&buf);
|
||||
bch2_rbio_error(rbio, READ_RETRY_AVOID, BLK_STS_IOERR);
|
||||
bch2_rbio_punt(rbio, bch2_read_csum_err, RBIO_CONTEXT_UNBOUND, system_unbound_wq);
|
||||
goto out;
|
||||
decompression_err:
|
||||
bch_err_inum_offset_ratelimited(c, rbio->read_pos.inode,
|
||||
rbio->read_pos.offset << 9,
|
||||
"decompression error");
|
||||
bch2_rbio_error(rbio, READ_ERR, BLK_STS_IOERR);
|
||||
bch2_rbio_punt(rbio, bch2_read_decompress_err, RBIO_CONTEXT_UNBOUND, system_unbound_wq);
|
||||
goto out;
|
||||
decrypt_err:
|
||||
bch_err_inum_offset_ratelimited(c, rbio->read_pos.inode,
|
||||
rbio->read_pos.offset << 9,
|
||||
"decrypt error");
|
||||
bch2_rbio_error(rbio, READ_ERR, BLK_STS_IOERR);
|
||||
bch2_rbio_punt(rbio, bch2_read_decrypt_err, RBIO_CONTEXT_UNBOUND, system_unbound_wq);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -716,16 +800,8 @@ static void bch2_read_endio(struct bio *bio)
|
||||
if (!rbio->split)
|
||||
rbio->bio.bi_end_io = rbio->end_io;
|
||||
|
||||
if (bio->bi_status) {
|
||||
if (ca) {
|
||||
bch_err_inum_offset_ratelimited(ca,
|
||||
rbio->read_pos.inode,
|
||||
rbio->read_pos.offset,
|
||||
"data read error: %s",
|
||||
bch2_blk_status_to_str(bio->bi_status));
|
||||
bch2_io_error(ca, BCH_MEMBER_ERROR_read);
|
||||
}
|
||||
bch2_rbio_error(rbio, READ_RETRY_AVOID, bio->bi_status);
|
||||
if (unlikely(bio->bi_status)) {
|
||||
bch2_rbio_punt(rbio, bch2_read_io_err, RBIO_CONTEXT_UNBOUND, system_unbound_wq);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -832,25 +908,22 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
|
||||
|
||||
if (unlikely(pick_ret < 0)) {
|
||||
struct printbuf buf = PRINTBUF;
|
||||
bch2_read_err_msg_trans(trans, &buf, orig, read_pos);
|
||||
prt_printf(&buf, "no device to read from: %s\n ", bch2_err_str(pick_ret));
|
||||
bch2_bkey_val_to_text(&buf, c, k);
|
||||
|
||||
bch_err_inum_offset_ratelimited(c,
|
||||
read_pos.inode, read_pos.offset << 9,
|
||||
"no device to read from: %s\n %s",
|
||||
bch2_err_str(pick_ret),
|
||||
buf.buf);
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (unlikely(bch2_csum_type_is_encryption(pick.crc.csum_type)) && !c->chacha20) {
|
||||
struct printbuf buf = PRINTBUF;
|
||||
bch2_read_err_msg_trans(trans, &buf, orig, read_pos);
|
||||
prt_printf(&buf, "attempting to read encrypted data without encryption key\n ");
|
||||
bch2_bkey_val_to_text(&buf, c, k);
|
||||
|
||||
bch_err_inum_offset_ratelimited(c,
|
||||
read_pos.inode, read_pos.offset << 9,
|
||||
"attempting to read encrypted data without encryption key\n %s",
|
||||
buf.buf);
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
goto err;
|
||||
}
|
||||
@ -1036,11 +1109,15 @@ int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
|
||||
}
|
||||
|
||||
if (!rbio->pick.idx) {
|
||||
if (!rbio->have_ioref) {
|
||||
bch_err_inum_offset_ratelimited(c,
|
||||
read_pos.inode,
|
||||
read_pos.offset << 9,
|
||||
"no device to read from");
|
||||
if (unlikely(!rbio->have_ioref)) {
|
||||
struct printbuf buf = PRINTBUF;
|
||||
bch2_read_err_msg_trans(trans, &buf, rbio, read_pos);
|
||||
prt_printf(&buf, "no device to read from:\n ");
|
||||
bch2_bkey_val_to_text(&buf, c, k);
|
||||
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
|
||||
bch2_rbio_error(rbio, READ_RETRY_AVOID, BLK_STS_IOERR);
|
||||
goto out;
|
||||
}
|
||||
@ -1202,16 +1279,20 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
|
||||
}
|
||||
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
bch2_trans_put(trans);
|
||||
bch2_bkey_buf_exit(&sk, c);
|
||||
|
||||
if (ret) {
|
||||
bch_err_inum_offset_ratelimited(c, inum.inum,
|
||||
bvec_iter.bi_sector << 9,
|
||||
"read error %i from btree lookup", ret);
|
||||
struct printbuf buf = PRINTBUF;
|
||||
bch2_inum_offset_err_msg_trans(trans, &buf, inum, bvec_iter.bi_sector << 9);
|
||||
prt_printf(&buf, "read error %i from btree lookup", ret);
|
||||
bch_err_ratelimited(c, "%s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
|
||||
rbio->bio.bi_status = BLK_STS_IOERR;
|
||||
bch2_rbio_done(rbio);
|
||||
}
|
||||
|
||||
bch2_trans_put(trans);
|
||||
bch2_bkey_buf_exit(&sk, c);
|
||||
}
|
||||
|
||||
void bch2_fs_io_read_exit(struct bch_fs *c)
|
||||
|
Loading…
Reference in New Issue
Block a user