Commit 94f651e2 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Return errors from for_each_btree_key()

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 201a4d4c
...@@ -273,14 +273,14 @@ int bch2_alloc_read(struct bch_fs *c, struct journal_keys *journal_keys) ...@@ -273,14 +273,14 @@ int bch2_alloc_read(struct bch_fs *c, struct journal_keys *journal_keys)
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_ALLOC, POS_MIN, 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_ALLOC, POS_MIN, 0, k, ret)
bch2_alloc_read_key(c, k); bch2_alloc_read_key(c, k);
bch2_trans_cond_resched(&trans);
}
ret = bch2_trans_exit(&trans); ret = bch2_trans_exit(&trans) ?: ret;
if (ret) if (ret) {
bch_err(c, "error reading alloc info: %i", ret);
return ret; return ret;
}
for_each_journal_key(*journal_keys, j) for_each_journal_key(*journal_keys, j)
if (j->btree_id == BTREE_ID_ALLOC) if (j->btree_id == BTREE_ID_ALLOC)
......
...@@ -289,7 +289,7 @@ static int mark_journal_key(struct bch_fs *c, enum btree_id id, ...@@ -289,7 +289,7 @@ static int mark_journal_key(struct bch_fs *c, enum btree_id id,
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, id, bkey_start_pos(&insert->k), for_each_btree_key(&trans, iter, id, bkey_start_pos(&insert->k),
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k, ret) {
percpu_down_read(&c->mark_lock); percpu_down_read(&c->mark_lock);
ret = bch2_mark_overwrite(&trans, iter, k, insert, NULL, ret = bch2_mark_overwrite(&trans, iter, k, insert, NULL,
BCH_BUCKET_MARK_GC| BCH_BUCKET_MARK_GC|
...@@ -300,7 +300,7 @@ static int mark_journal_key(struct bch_fs *c, enum btree_id id, ...@@ -300,7 +300,7 @@ static int mark_journal_key(struct bch_fs *c, enum btree_id id,
break; break;
} }
return bch2_trans_exit(&trans); return bch2_trans_exit(&trans) ?: ret;
} }
static int bch2_gc_btrees(struct bch_fs *c, struct journal_keys *journal_keys, static int bch2_gc_btrees(struct bch_fs *c, struct journal_keys *journal_keys,
......
...@@ -238,12 +238,16 @@ static inline struct bkey_s_c __bch2_btree_iter_next(struct btree_iter *iter, ...@@ -238,12 +238,16 @@ static inline struct bkey_s_c __bch2_btree_iter_next(struct btree_iter *iter,
: bch2_btree_iter_next(iter); : bch2_btree_iter_next(iter);
} }
#define for_each_btree_key(_trans, _iter, _btree_id, _start, _flags, _k)\ #define for_each_btree_key(_trans, _iter, _btree_id, \
for (iter = bch2_trans_get_iter((_trans), (_btree_id), \ _start, _flags, _k, _ret) \
(_start), (_flags)), \ for ((_ret) = PTR_ERR_OR_ZERO((_iter) = \
(_k) = __bch2_btree_iter_peek(_iter, _flags); \ bch2_trans_get_iter((_trans), (_btree_id), \
!IS_ERR_OR_NULL((_k).k); \ (_start), (_flags))) ?: \
(_k) = __bch2_btree_iter_next(_iter, _flags)) PTR_ERR_OR_ZERO(((_k) = \
__bch2_btree_iter_peek(_iter, _flags)).k); \
!ret && (_k).k; \
(_ret) = PTR_ERR_OR_ZERO(((_k) = \
__bch2_btree_iter_next(_iter, _flags)).k))
#define for_each_btree_key_continue(_iter, _flags, _k) \ #define for_each_btree_key_continue(_iter, _flags, _k) \
for ((_k) = __bch2_btree_iter_peek(_iter, _flags); \ for ((_k) = __bch2_btree_iter_peek(_iter, _flags); \
......
...@@ -1035,12 +1035,12 @@ int bch2_mark_key(struct bch_fs *c, struct bkey_s_c k, ...@@ -1035,12 +1035,12 @@ int bch2_mark_key(struct bch_fs *c, struct bkey_s_c k,
return ret; return ret;
} }
inline bool bch2_mark_overwrite(struct btree_trans *trans, inline int bch2_mark_overwrite(struct btree_trans *trans,
struct btree_iter *iter, struct btree_iter *iter,
struct bkey_s_c old, struct bkey_s_c old,
struct bkey_i *new, struct bkey_i *new,
struct bch_fs_usage *fs_usage, struct bch_fs_usage *fs_usage,
unsigned flags) unsigned flags)
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct btree *b = iter->l[0].b; struct btree *b = iter->l[0].b;
...@@ -1049,7 +1049,7 @@ inline bool bch2_mark_overwrite(struct btree_trans *trans, ...@@ -1049,7 +1049,7 @@ inline bool bch2_mark_overwrite(struct btree_trans *trans,
if (btree_node_is_extents(b) if (btree_node_is_extents(b)
? bkey_cmp(new->k.p, bkey_start_pos(old.k)) <= 0 ? bkey_cmp(new->k.p, bkey_start_pos(old.k)) <= 0
: bkey_cmp(new->k.p, old.k->p)) : bkey_cmp(new->k.p, old.k->p))
return false; return 0;
if (btree_node_is_extents(b)) { if (btree_node_is_extents(b)) {
switch (bch2_extent_overlap(&new->k, old.k)) { switch (bch2_extent_overlap(&new->k, old.k)) {
...@@ -1080,24 +1080,24 @@ inline bool bch2_mark_overwrite(struct btree_trans *trans, ...@@ -1080,24 +1080,24 @@ inline bool bch2_mark_overwrite(struct btree_trans *trans,
BUG_ON(sectors >= 0); BUG_ON(sectors >= 0);
} }
bch2_mark_key_locked(c, old, false, sectors, return bch2_mark_key_locked(c, old, false, sectors, fs_usage,
fs_usage, trans->journal_res.seq, flags); trans->journal_res.seq, flags) ?: 1;
return true;
} }
void bch2_mark_update(struct btree_trans *trans, int bch2_mark_update(struct btree_trans *trans,
struct btree_insert_entry *insert, struct btree_insert_entry *insert,
struct bch_fs_usage *fs_usage, struct bch_fs_usage *fs_usage,
unsigned flags) unsigned flags)
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
struct btree_iter *iter = insert->iter; struct btree_iter *iter = insert->iter;
struct btree *b = iter->l[0].b; struct btree *b = iter->l[0].b;
struct btree_node_iter node_iter = iter->l[0].iter; struct btree_node_iter node_iter = iter->l[0].iter;
struct bkey_packed *_k; struct bkey_packed *_k;
int ret = 0;
if (!btree_node_type_needs_gc(iter->btree_id)) if (!btree_node_type_needs_gc(iter->btree_id))
return; return 0;
bch2_mark_key_locked(c, bkey_i_to_s_c(insert->k), true, bch2_mark_key_locked(c, bkey_i_to_s_c(insert->k), true,
bpos_min(insert->k->k.p, b->key.k.p).offset - bpos_min(insert->k->k.p, b->key.k.p).offset -
...@@ -1105,7 +1105,7 @@ void bch2_mark_update(struct btree_trans *trans, ...@@ -1105,7 +1105,7 @@ void bch2_mark_update(struct btree_trans *trans,
fs_usage, trans->journal_res.seq, flags); fs_usage, trans->journal_res.seq, flags);
if (unlikely(trans->flags & BTREE_INSERT_NOMARK_OVERWRITES)) if (unlikely(trans->flags & BTREE_INSERT_NOMARK_OVERWRITES))
return; return 0;
/* /*
* For non extents, we only mark the new key, not the key being * For non extents, we only mark the new key, not the key being
...@@ -1114,19 +1114,22 @@ void bch2_mark_update(struct btree_trans *trans, ...@@ -1114,19 +1114,22 @@ void bch2_mark_update(struct btree_trans *trans,
if ((iter->btree_id == BTREE_ID_ALLOC || if ((iter->btree_id == BTREE_ID_ALLOC ||
iter->btree_id == BTREE_ID_EC) && iter->btree_id == BTREE_ID_EC) &&
!bkey_deleted(&insert->k->k)) !bkey_deleted(&insert->k->k))
return; return 0;
while ((_k = bch2_btree_node_iter_peek_filter(&node_iter, b, while ((_k = bch2_btree_node_iter_peek_filter(&node_iter, b,
KEY_TYPE_discard))) { KEY_TYPE_discard))) {
struct bkey unpacked; struct bkey unpacked;
struct bkey_s_c k = bkey_disassemble(b, _k, &unpacked); struct bkey_s_c k = bkey_disassemble(b, _k, &unpacked);
if (!bch2_mark_overwrite(trans, iter, k, insert->k, ret = bch2_mark_overwrite(trans, iter, k, insert->k,
fs_usage, flags)) fs_usage, flags);
if (ret <= 0)
break; break;
bch2_btree_node_iter_advance(&node_iter, b); bch2_btree_node_iter_advance(&node_iter, b);
} }
return ret;
} }
void bch2_trans_fs_usage_apply(struct btree_trans *trans, void bch2_trans_fs_usage_apply(struct btree_trans *trans,
......
...@@ -254,11 +254,11 @@ int bch2_mark_key(struct bch_fs *, struct bkey_s_c, ...@@ -254,11 +254,11 @@ int bch2_mark_key(struct bch_fs *, struct bkey_s_c,
int bch2_fs_usage_apply(struct bch_fs *, struct bch_fs_usage *, int bch2_fs_usage_apply(struct bch_fs *, struct bch_fs_usage *,
struct disk_reservation *); struct disk_reservation *);
bool bch2_mark_overwrite(struct btree_trans *, struct btree_iter *, int bch2_mark_overwrite(struct btree_trans *, struct btree_iter *,
struct bkey_s_c, struct bkey_i *, struct bkey_s_c, struct bkey_i *,
struct bch_fs_usage *, unsigned); struct bch_fs_usage *, unsigned);
void bch2_mark_update(struct btree_trans *, struct btree_insert_entry *, int bch2_mark_update(struct btree_trans *, struct btree_insert_entry *,
struct bch_fs_usage *, unsigned); struct bch_fs_usage *, unsigned);
void bch2_trans_fs_usage_apply(struct btree_trans *, struct bch_fs_usage *); void bch2_trans_fs_usage_apply(struct btree_trans *, struct bch_fs_usage *);
/* disk reservations: */ /* disk reservations: */
......
...@@ -333,14 +333,10 @@ int bch2_empty_dir_trans(struct btree_trans *trans, u64 dir_inum) ...@@ -333,14 +333,10 @@ int bch2_empty_dir_trans(struct btree_trans *trans, u64 dir_inum)
{ {
struct btree_iter *iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret;
iter = bch2_trans_get_iter(trans, BTREE_ID_DIRENTS,
POS(dir_inum, 0), 0);
if (IS_ERR(iter))
return PTR_ERR(iter);
for_each_btree_key_continue(iter, 0, k) { for_each_btree_key(trans, iter, BTREE_ID_DIRENTS,
POS(dir_inum, 0), 0, k, ret) {
if (k.k->p.inode > dir_inum) if (k.k->p.inode > dir_inum)
break; break;
...@@ -369,6 +365,7 @@ int bch2_readdir(struct bch_fs *c, struct file *file, ...@@ -369,6 +365,7 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_s_c_dirent dirent; struct bkey_s_c_dirent dirent;
unsigned len; unsigned len;
int ret;
if (!dir_emit_dots(file, ctx)) if (!dir_emit_dots(file, ctx))
return 0; return 0;
...@@ -376,7 +373,7 @@ int bch2_readdir(struct bch_fs *c, struct file *file, ...@@ -376,7 +373,7 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS,
POS(inode->v.i_ino, ctx->pos), 0, k) { POS(inode->v.i_ino, ctx->pos), 0, k, ret) {
if (k.k->type != KEY_TYPE_dirent) if (k.k->type != KEY_TYPE_dirent)
continue; continue;
...@@ -401,7 +398,7 @@ int bch2_readdir(struct bch_fs *c, struct file *file, ...@@ -401,7 +398,7 @@ int bch2_readdir(struct bch_fs *c, struct file *file,
ctx->pos = k.k->p.offset + 1; ctx->pos = k.k->p.offset + 1;
} }
bch2_trans_exit(&trans); ret = bch2_trans_exit(&trans) ?: ret;
return 0; return ret;
} }
...@@ -679,10 +679,8 @@ static int ec_stripe_bkey_insert(struct bch_fs *c, ...@@ -679,10 +679,8 @@ static int ec_stripe_bkey_insert(struct bch_fs *c,
bch2_trans_begin(&trans); bch2_trans_begin(&trans);
/* XXX: start pos hint */ /* XXX: start pos hint */
iter = bch2_trans_get_iter(&trans, BTREE_ID_EC, POS_MIN, for_each_btree_key(&trans, iter, BTREE_ID_EC, POS_MIN,
BTREE_ITER_SLOTS|BTREE_ITER_INTENT); BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
for_each_btree_key_continue(iter, BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k) {
if (bkey_cmp(k.k->p, POS(0, U32_MAX)) > 0) if (bkey_cmp(k.k->p, POS(0, U32_MAX)) > 0)
break; break;
...@@ -690,7 +688,8 @@ static int ec_stripe_bkey_insert(struct bch_fs *c, ...@@ -690,7 +688,8 @@ static int ec_stripe_bkey_insert(struct bch_fs *c,
goto found_slot; goto found_slot;
} }
ret = -ENOSPC; if (!ret)
ret = -ENOSPC;
goto out; goto out;
found_slot: found_slot:
ret = ec_stripe_mem_alloc(c, iter); ret = ec_stripe_mem_alloc(c, iter);
...@@ -1249,14 +1248,14 @@ int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys) ...@@ -1249,14 +1248,14 @@ int bch2_stripes_read(struct bch_fs *c, struct journal_keys *journal_keys)
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EC, POS_MIN, 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_EC, POS_MIN, 0, k, ret)
bch2_stripe_read_key(c, k); bch2_stripe_read_key(c, k);
bch2_trans_cond_resched(&trans);
}
ret = bch2_trans_exit(&trans); ret = bch2_trans_exit(&trans) ?: ret;
if (ret) if (ret) {
bch_err(c, "error reading stripes: %i", ret);
return ret; return ret;
}
for_each_journal_key(*journal_keys, i) for_each_journal_key(*journal_keys, i)
if (i->btree_id == BTREE_ID_EC) if (i->btree_id == BTREE_ID_EC)
......
...@@ -1632,13 +1632,14 @@ bool bch2_check_range_allocated(struct bch_fs *c, struct bpos pos, u64 size, ...@@ -1632,13 +1632,14 @@ bool bch2_check_range_allocated(struct bch_fs *c, struct bpos pos, u64 size,
struct bpos end = pos; struct bpos end = pos;
struct bkey_s_c k; struct bkey_s_c k;
bool ret = true; bool ret = true;
int err;
end.offset += size; end.offset += size;
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, pos, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, pos,
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k, err) {
if (bkey_cmp(bkey_start_pos(k.k), end) >= 0) if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
break; break;
......
...@@ -2139,7 +2139,7 @@ static inline int range_has_data(struct bch_fs *c, ...@@ -2139,7 +2139,7 @@ static inline int range_has_data(struct bch_fs *c,
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, start, 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, start, 0, k, ret) {
if (bkey_cmp(bkey_start_pos(k.k), end) >= 0) if (bkey_cmp(bkey_start_pos(k.k), end) >= 0)
break; break;
...@@ -2732,7 +2732,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset) ...@@ -2732,7 +2732,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(inode->v.i_ino, offset >> 9), 0, k) { POS(inode->v.i_ino, offset >> 9), 0, k, ret) {
if (k.k->p.inode != inode->v.i_ino) { if (k.k->p.inode != inode->v.i_ino) {
break; break;
} else if (bkey_extent_is_data(k.k)) { } else if (bkey_extent_is_data(k.k)) {
...@@ -2742,7 +2742,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset) ...@@ -2742,7 +2742,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
break; break;
} }
ret = bch2_trans_exit(&trans); ret = bch2_trans_exit(&trans) ?: ret;
if (ret) if (ret)
return ret; return ret;
...@@ -2806,7 +2806,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset) ...@@ -2806,7 +2806,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(inode->v.i_ino, offset >> 9), POS(inode->v.i_ino, offset >> 9),
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k, ret) {
if (k.k->p.inode != inode->v.i_ino) { if (k.k->p.inode != inode->v.i_ino) {
next_hole = bch2_next_pagecache_hole(&inode->v, next_hole = bch2_next_pagecache_hole(&inode->v,
offset, MAX_LFS_FILESIZE); offset, MAX_LFS_FILESIZE);
...@@ -2823,7 +2823,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset) ...@@ -2823,7 +2823,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
} }
} }
ret = bch2_trans_exit(&trans); ret = bch2_trans_exit(&trans) ?: ret;
if (ret) if (ret)
return ret; return ret;
......
...@@ -1210,7 +1210,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, ...@@ -1210,7 +1210,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(ei->v.i_ino, start >> 9), 0, k) POS(ei->v.i_ino, start >> 9), 0, k, ret)
if (bkey_extent_is_data(k.k) || if (bkey_extent_is_data(k.k) ||
k.k->type == KEY_TYPE_reservation) { k.k->type == KEY_TYPE_reservation) {
if (bkey_cmp(bkey_start_pos(k.k), if (bkey_cmp(bkey_start_pos(k.k),
...@@ -1220,17 +1220,17 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, ...@@ -1220,17 +1220,17 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
if (have_extent) { if (have_extent) {
ret = bch2_fill_extent(info, &tmp.k, 0); ret = bch2_fill_extent(info, &tmp.k, 0);
if (ret) if (ret)
goto out; break;
} }
bkey_reassemble(&tmp.k, k); bkey_reassemble(&tmp.k, k);
have_extent = true; have_extent = true;
} }
if (have_extent) if (!ret && have_extent)
ret = bch2_fill_extent(info, &tmp.k, FIEMAP_EXTENT_LAST); ret = bch2_fill_extent(info, &tmp.k, FIEMAP_EXTENT_LAST);
out:
bch2_trans_exit(&trans); ret = bch2_trans_exit(&trans) ?: ret;
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
......
...@@ -21,8 +21,10 @@ static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum) ...@@ -21,8 +21,10 @@ static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum)
struct btree_iter *iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 sectors = 0; u64 sectors = 0;
int ret;
for_each_btree_key(trans, iter, BTREE_ID_EXTENTS, POS(inum, 0), 0, k) { for_each_btree_key(trans, iter, BTREE_ID_EXTENTS,
POS(inum, 0), 0, k, ret) {
if (k.k->p.inode != inum) if (k.k->p.inode != inum)
break; break;
...@@ -30,7 +32,9 @@ static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum) ...@@ -30,7 +32,9 @@ static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum)
sectors += k.k->size; sectors += k.k->size;
} }
return bch2_trans_iter_free(trans, iter) ?: sectors; bch2_trans_iter_free(trans, iter);
return ret ?: sectors;
} }
static int remove_dirent(struct btree_trans *trans, static int remove_dirent(struct btree_trans *trans,
...@@ -942,7 +946,7 @@ static int check_directory_structure(struct bch_fs *c, ...@@ -942,7 +946,7 @@ static int check_directory_structure(struct bch_fs *c,
goto up; goto up;
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS,
POS(e->inum, e->offset + 1), 0, k) { POS(e->inum, e->offset + 1), 0, k, ret) {
if (k.k->p.inode != e->inum) if (k.k->p.inode != e->inum)
break; break;
...@@ -985,7 +989,7 @@ static int check_directory_structure(struct bch_fs *c, ...@@ -985,7 +989,7 @@ static int check_directory_structure(struct bch_fs *c,
} }
goto next; goto next;
} }
ret = bch2_trans_iter_free(&trans, iter); ret = bch2_trans_iter_free(&trans, iter) ?: ret;
if (ret) { if (ret) {
bch_err(c, "btree error %i in fsck", ret); bch_err(c, "btree error %i in fsck", ret);
goto err; goto err;
...@@ -1087,7 +1091,7 @@ static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links, ...@@ -1087,7 +1091,7 @@ static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links,
inc_link(c, links, range_start, range_end, BCACHEFS_ROOT_INO, false); inc_link(c, links, range_start, range_end, BCACHEFS_ROOT_INO, false);
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN, 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN, 0, k, ret) {
switch (k.k->type) { switch (k.k->type) {
case KEY_TYPE_dirent: case KEY_TYPE_dirent:
d = bkey_s_c_to_dirent(k); d = bkey_s_c_to_dirent(k);
...@@ -1105,7 +1109,7 @@ static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links, ...@@ -1105,7 +1109,7 @@ static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links,
bch2_trans_cond_resched(&trans); bch2_trans_cond_resched(&trans);
} }
ret = bch2_trans_exit(&trans); ret = bch2_trans_exit(&trans) ?: ret;
if (ret) if (ret)
bch_err(c, "error in fs gc: btree error %i while walking dirents", ret); bch_err(c, "error in fs gc: btree error %i while walking dirents", ret);
...@@ -1432,15 +1436,12 @@ static int check_inodes_fast(struct bch_fs *c) ...@@ -1432,15 +1436,12 @@ static int check_inodes_fast(struct bch_fs *c)
struct btree_iter *iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_s_c_inode inode; struct bkey_s_c_inode inode;
int ret = 0, ret2; int ret;
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
bch2_trans_preload_iters(&trans); bch2_trans_preload_iters(&trans);
iter = bch2_trans_get_iter(&trans, BTREE_ID_INODES, for_each_btree_key(&trans, iter, BTREE_ID_INODES, POS_MIN, 0, k, ret) {
POS_MIN, 0);
for_each_btree_key_continue(iter, 0, k) {
if (k.k->type != KEY_TYPE_inode) if (k.k->type != KEY_TYPE_inode)
continue; continue;
...@@ -1456,10 +1457,9 @@ static int check_inodes_fast(struct bch_fs *c) ...@@ -1456,10 +1457,9 @@ static int check_inodes_fast(struct bch_fs *c)
break; break;
} }
} }
BUG_ON(ret == -EINTR);
ret2 = bch2_trans_exit(&trans); return bch2_trans_exit(&trans) ?: ret;
return ret ?: ret2;
} }
/* /*
......
...@@ -1326,7 +1326,7 @@ static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio, ...@@ -1326,7 +1326,7 @@ static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio,
retry: retry:
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(inode, bvec_iter.bi_sector), POS(inode, bvec_iter.bi_sector),
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k, ret) {
BKEY_PADDED(k) tmp; BKEY_PADDED(k) tmp;
unsigned bytes; unsigned bytes;
...@@ -1357,8 +1357,8 @@ static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio, ...@@ -1357,8 +1357,8 @@ static void bch2_read_retry(struct bch_fs *c, struct bch_read_bio *rbio,
* If we get here, it better have been because there was an error * If we get here, it better have been because there was an error
* reading a btree node * reading a btree node
*/ */
BUG_ON(!btree_iter_err(iter)); BUG_ON(!ret);
__bcache_io_error(c, "btree IO error"); __bcache_io_error(c, "btree IO error: %i", ret);
err: err:
rbio->bio.bi_status = BLK_STS_IOERR; rbio->bio.bi_status = BLK_STS_IOERR;
out: out:
...@@ -1871,6 +1871,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode) ...@@ -1871,6 +1871,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
unsigned flags = BCH_READ_RETRY_IF_STALE| unsigned flags = BCH_READ_RETRY_IF_STALE|
BCH_READ_MAY_PROMOTE| BCH_READ_MAY_PROMOTE|
BCH_READ_USER_MAPPED; BCH_READ_USER_MAPPED;
int ret;
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
...@@ -1883,7 +1884,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode) ...@@ -1883,7 +1884,7 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(inode, rbio->bio.bi_iter.bi_sector), POS(inode, rbio->bio.bi_iter.bi_sector),
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k, ret) {
BKEY_PADDED(k) tmp; BKEY_PADDED(k) tmp;
unsigned bytes; unsigned bytes;
...@@ -1915,8 +1916,8 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode) ...@@ -1915,8 +1916,8 @@ void bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, u64 inode)
* If we get here, it better have been because there was an error * If we get here, it better have been because there was an error
* reading a btree node * reading a btree node
*/ */
BUG_ON(!btree_iter_err(iter)); BUG_ON(!ret);
bcache_io_error(c, &rbio->bio, "btree IO error"); bcache_io_error(c, &rbio->bio, "btree IO error: %i", ret);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
bch2_rbio_done(rbio); bch2_rbio_done(rbio);
......
...@@ -630,7 +630,7 @@ static int bch2_gc_data_replicas(struct bch_fs *c) ...@@ -630,7 +630,7 @@ static int bch2_gc_data_replicas(struct bch_fs *c)
bch2_replicas_gc_start(c, (1 << BCH_DATA_USER)|(1 << BCH_DATA_CACHED)); bch2_replicas_gc_start(c, (1 << BCH_DATA_USER)|(1 << BCH_DATA_CACHED));
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS_MIN, for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS_MIN,
BTREE_ITER_PREFETCH, k) { BTREE_ITER_PREFETCH, k, ret) {
ret = bch2_mark_bkey_replicas(c, k); ret = bch2_mark_bkey_replicas(c, k);
if (ret) if (ret)
break; break;
......
...@@ -364,7 +364,7 @@ static int bch2_quota_init_type(struct bch_fs *c, enum quota_types type) ...@@ -364,7 +364,7 @@ static int bch2_quota_init_type(struct bch_fs *c, enum quota_types type)
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_QUOTAS, POS(type, 0), for_each_btree_key(&trans, iter, BTREE_ID_QUOTAS, POS(type, 0),
BTREE_ITER_PREFETCH, k) { BTREE_ITER_PREFETCH, k, ret) {
if (k.k->p.inode != type) if (k.k->p.inode != type)
break; break;
...@@ -436,7 +436,7 @@ int bch2_fs_quota_read(struct bch_fs *c) ...@@ -436,7 +436,7 @@ int bch2_fs_quota_read(struct bch_fs *c)
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_INODES, POS_MIN, for_each_btree_key(&trans, iter, BTREE_ID_INODES, POS_MIN,
BTREE_ITER_PREFETCH, k) { BTREE_ITER_PREFETCH, k, ret) {
switch (k.k->type) { switch (k.k->type) {
case KEY_TYPE_inode: case KEY_TYPE_inode:
ret = bch2_inode_unpack(bkey_s_c_to_inode(k), &u); ret = bch2_inode_unpack(bkey_s_c_to_inode(k), &u);
......
...@@ -134,14 +134,11 @@ bch2_hash_lookup(struct btree_trans *trans, ...@@ -134,14 +134,11 @@ bch2_hash_lookup(struct btree_trans *trans,
{ {
struct btree_iter *iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret;
iter = bch2_trans_get_iter(trans, desc.btree_id, for_each_btree_key(trans, iter, desc.btree_id,
POS(inode, desc.hash_key(info, key)), POS(inode, desc.hash_key(info, key)),
BTREE_ITER_SLOTS|flags); BTREE_ITER_SLOTS|flags, k, ret) {
if (IS_ERR(iter))
return iter;
for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, k) {
if (iter->pos.inode != inode) if (iter->pos.inode != inode)
break; break;
...@@ -156,7 +153,7 @@ bch2_hash_lookup(struct btree_trans *trans, ...@@ -156,7 +153,7 @@ bch2_hash_lookup(struct btree_trans *trans,
} }
} }
return IS_ERR(k.k) ? ERR_CAST(k.k) : ERR_PTR(-ENOENT); return ERR_PTR(ret ?: -ENOENT);
} }
static __always_inline struct btree_iter * static __always_inline struct btree_iter *
...@@ -167,14 +164,11 @@ bch2_hash_hole(struct btree_trans *trans, ...@@ -167,14 +164,11 @@ bch2_hash_hole(struct btree_trans *trans,
{ {
struct btree_iter *iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret;
iter = bch2_trans_get_iter(trans, desc.btree_id, for_each_btree_key(trans, iter, desc.btree_id,
POS(inode, desc.hash_key(info, key)), POS(inode, desc.hash_key(info, key)),
BTREE_ITER_SLOTS|BTREE_ITER_INTENT); BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
if (IS_ERR(iter))
return iter;
for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, k) {
if (iter->pos.inode != inode) if (iter->pos.inode != inode)
break; break;
...@@ -182,7 +176,7 @@ bch2_hash_hole(struct btree_trans *trans, ...@@ -182,7 +176,7 @@ bch2_hash_hole(struct btree_trans *trans,
return iter; return iter;
} }
return IS_ERR(k.k) ? ERR_CAST(k.k) : ERR_PTR(-ENOSPC); return ERR_PTR(ret ?: -ENOSPC);
} }
static __always_inline static __always_inline
...@@ -224,15 +218,11 @@ int bch2_hash_set(struct btree_trans *trans, ...@@ -224,15 +218,11 @@ int bch2_hash_set(struct btree_trans *trans,
struct btree_iter *iter, *slot = NULL; struct btree_iter *iter, *slot = NULL;
struct bkey_s_c k; struct bkey_s_c k;
bool found = false; bool found = false;
int ret = 0; int ret;
iter = bch2_trans_get_iter(trans, desc.btree_id,
POS(inode, desc.hash_bkey(info, bkey_i_to_s_c(insert))),
BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
if (IS_ERR(iter))
return PTR_ERR(iter);
for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, k) { for_each_btree_key(trans, iter, desc.btree_id,
POS(inode, desc.hash_bkey(info, bkey_i_to_s_c(insert))),
BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
if (iter->pos.inode != inode) if (iter->pos.inode != inode)
break; break;
...@@ -256,9 +246,10 @@ int bch2_hash_set(struct btree_trans *trans, ...@@ -256,9 +246,10 @@ int bch2_hash_set(struct btree_trans *trans,
} }
if (slot) if (slot)
bch2_trans_iter_free(trans, iter); bch2_trans_iter_free(trans, slot);
bch2_trans_iter_free(trans, iter);
return bch2_trans_iter_free(trans, iter) ?: -ENOSPC; return ret ?: -ENOSPC;
found: found:
found = true; found = true;
not_found: not_found:
......
...@@ -289,13 +289,14 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf) ...@@ -289,13 +289,14 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf)
nr_compressed_extents = 0, nr_compressed_extents = 0,
compressed_sectors_compressed = 0, compressed_sectors_compressed = 0,
compressed_sectors_uncompressed = 0; compressed_sectors_uncompressed = 0;
int ret;
if (!test_bit(BCH_FS_STARTED, &c->flags)) if (!test_bit(BCH_FS_STARTED, &c->flags))
return -EPERM; return -EPERM;
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS_MIN, 0, k) for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS_MIN, 0, k, ret)
if (k.k->type == KEY_TYPE_extent) { if (k.k->type == KEY_TYPE_extent) {
struct bkey_s_c_extent e = bkey_s_c_to_extent(k); struct bkey_s_c_extent e = bkey_s_c_to_extent(k);
const union bch_extent_entry *entry; const union bch_extent_entry *entry;
...@@ -317,7 +318,10 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf) ...@@ -317,7 +318,10 @@ static ssize_t bch2_compression_stats(struct bch_fs *c, char *buf)
break; break;
} }
} }
bch2_trans_exit(&trans);
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)
return ret;
return scnprintf(buf, PAGE_SIZE, return scnprintf(buf, PAGE_SIZE,
"uncompressed data:\n" "uncompressed data:\n"
......
...@@ -116,7 +116,8 @@ static void test_iterate(struct bch_fs *c, u64 nr) ...@@ -116,7 +116,8 @@ static void test_iterate(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS(0, 0), 0, k) for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS,
POS_MIN, 0, k, ret)
BUG_ON(k.k->p.offset != i++); BUG_ON(k.k->p.offset != i++);
BUG_ON(i != nr); BUG_ON(i != nr);
...@@ -161,7 +162,8 @@ static void test_iterate_extents(struct bch_fs *c, u64 nr) ...@@ -161,7 +162,8 @@ static void test_iterate_extents(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS(0, 0), 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS_MIN, 0, k, ret) {
BUG_ON(bkey_start_offset(k.k) != i); BUG_ON(bkey_start_offset(k.k) != i);
i = k.k->p.offset; i = k.k->p.offset;
} }
...@@ -209,7 +211,8 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr) ...@@ -209,7 +211,8 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS(0, 0), 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN,
0, k, ret) {
BUG_ON(k.k->p.offset != i); BUG_ON(k.k->p.offset != i);
i += 2; i += 2;
} }
...@@ -221,8 +224,8 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr) ...@@ -221,8 +224,8 @@ static void test_iterate_slots(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS(0, 0), for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN,
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k, ret) {
BUG_ON(bkey_deleted(k.k) != (i & 1)); BUG_ON(bkey_deleted(k.k) != (i & 1));
BUG_ON(k.k->p.offset != i++); BUG_ON(k.k->p.offset != i++);
...@@ -263,7 +266,8 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr) ...@@ -263,7 +266,8 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS(0, 0), 0, k) { for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS_MIN,
0, k, ret) {
BUG_ON(bkey_start_offset(k.k) != i + 8); BUG_ON(bkey_start_offset(k.k) != i + 8);
BUG_ON(k.k->size != 8); BUG_ON(k.k->size != 8);
i += 16; i += 16;
...@@ -276,8 +280,8 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr) ...@@ -276,8 +280,8 @@ static void test_iterate_slots_extents(struct bch_fs *c, u64 nr)
i = 0; i = 0;
for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS(0, 0), for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS, POS_MIN,
BTREE_ITER_SLOTS, k) { BTREE_ITER_SLOTS, k, ret) {
BUG_ON(bkey_deleted(k.k) != !(i % 16)); BUG_ON(bkey_deleted(k.k) != !(i % 16));
BUG_ON(bkey_start_offset(k.k) != i); BUG_ON(bkey_start_offset(k.k) != i);
...@@ -501,10 +505,8 @@ static void seq_insert(struct bch_fs *c, u64 nr) ...@@ -501,10 +505,8 @@ static void seq_insert(struct bch_fs *c, u64 nr)
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS, POS_MIN, for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN,
BTREE_ITER_SLOTS|BTREE_ITER_INTENT); BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
for_each_btree_key_continue(iter, BTREE_ITER_SLOTS, k) {
insert.k.p = iter->pos; insert.k.p = iter->pos;
bch2_trans_update(&trans, BTREE_INSERT_ENTRY(iter, &insert.k_i)); bch2_trans_update(&trans, BTREE_INSERT_ENTRY(iter, &insert.k_i));
...@@ -522,10 +524,11 @@ static void seq_lookup(struct bch_fs *c, u64 nr) ...@@ -522,10 +524,11 @@ static void seq_lookup(struct bch_fs *c, u64 nr)
struct btree_trans trans; struct btree_trans trans;
struct btree_iter *iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret;
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN, 0, k) for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN, 0, k, ret)
; ;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
} }
...@@ -539,10 +542,8 @@ static void seq_overwrite(struct bch_fs *c, u64 nr) ...@@ -539,10 +542,8 @@ static void seq_overwrite(struct bch_fs *c, u64 nr)
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
iter = bch2_trans_get_iter(&trans, BTREE_ID_DIRENTS, POS_MIN, for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN,
BTREE_ITER_INTENT); BTREE_ITER_INTENT, k, ret) {
for_each_btree_key_continue(iter, 0, k) {
struct bkey_i_cookie u; struct bkey_i_cookie u;
bkey_reassemble(&u.k_i, k); bkey_reassemble(&u.k_i, k);
......
...@@ -198,55 +198,54 @@ int bch2_xattr_set(struct btree_trans *trans, u64 inum, ...@@ -198,55 +198,54 @@ int bch2_xattr_set(struct btree_trans *trans, u64 inum,
return ret; return ret;
} }
static void __bch2_xattr_emit(const char *prefix, struct xattr_buf {
const char *name, size_t name_len, char *buf;
char **buffer, size_t *buffer_size, size_t len;
ssize_t *ret) size_t used;
};
static int __bch2_xattr_emit(const char *prefix,
const char *name, size_t name_len,
struct xattr_buf *buf)
{ {
const size_t prefix_len = strlen(prefix); const size_t prefix_len = strlen(prefix);
const size_t total_len = prefix_len + name_len + 1; const size_t total_len = prefix_len + name_len + 1;
if (*buffer) { if (buf->buf) {
if (total_len > *buffer_size) { if (buf->used + total_len > buf->len)
*ret = -ERANGE; return -ERANGE;
return;
}
memcpy(*buffer, prefix, prefix_len); memcpy(buf->buf + buf->used, prefix, prefix_len);
memcpy(*buffer + prefix_len, memcpy(buf->buf + buf->used + prefix_len,
name, name_len); name, name_len);
(*buffer)[prefix_len + name_len] = '\0'; buf->buf[buf->used + prefix_len + name_len] = '\0';
*buffer += total_len;
*buffer_size -= total_len;
} }
*ret += total_len; buf->used += total_len;
return 0;
} }
static void bch2_xattr_emit(struct dentry *dentry, static int bch2_xattr_emit(struct dentry *dentry,
const struct bch_xattr *xattr, const struct bch_xattr *xattr,
char **buffer, size_t *buffer_size, struct xattr_buf *buf)
ssize_t *ret)
{ {
const struct xattr_handler *handler = const struct xattr_handler *handler =
bch2_xattr_type_to_handler(xattr->x_type); bch2_xattr_type_to_handler(xattr->x_type);
if (handler && (!handler->list || handler->list(dentry))) return handler && (!handler->list || handler->list(dentry))
__bch2_xattr_emit(handler->prefix ?: handler->name, ? __bch2_xattr_emit(handler->prefix ?: handler->name,
xattr->x_name, xattr->x_name_len, xattr->x_name, xattr->x_name_len, buf)
buffer, buffer_size, ret); : 0;
} }
static void bch2_xattr_list_bcachefs(struct bch_fs *c, static int bch2_xattr_list_bcachefs(struct bch_fs *c,
struct bch_inode_info *inode, struct bch_inode_info *inode,
char **buffer, struct xattr_buf *buf,
size_t *buffer_size, bool all)
ssize_t *ret,
bool all)
{ {
const char *prefix = all ? "bcachefs_effective." : "bcachefs."; const char *prefix = all ? "bcachefs_effective." : "bcachefs.";
unsigned id; unsigned id;
int ret = 0;
u64 v; u64 v;
for (id = 0; id < Inode_opt_nr; id++) { for (id = 0; id < Inode_opt_nr; id++) {
...@@ -258,13 +257,13 @@ static void bch2_xattr_list_bcachefs(struct bch_fs *c, ...@@ -258,13 +257,13 @@ static void bch2_xattr_list_bcachefs(struct bch_fs *c,
!(inode->ei_inode.bi_fields_set & (1 << id))) !(inode->ei_inode.bi_fields_set & (1 << id)))
continue; continue;
__bch2_xattr_emit(prefix, ret = __bch2_xattr_emit(prefix, bch2_inode_opts[id],
bch2_inode_opts[id], strlen(bch2_inode_opts[id]), buf);
strlen(bch2_inode_opts[id]), if (ret)
buffer, buffer_size, ret);
if (*ret < 0)
break; break;
} }
return ret;
} }
ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
...@@ -274,13 +273,14 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) ...@@ -274,13 +273,14 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
struct btree_trans trans; struct btree_trans trans;
struct btree_iter *iter; struct btree_iter *iter;
struct bkey_s_c k; struct bkey_s_c k;
struct xattr_buf buf = { .buf = buffer, .len = buffer_size };
u64 inum = dentry->d_inode->i_ino; u64 inum = dentry->d_inode->i_ino;
ssize_t ret = 0; int ret;
bch2_trans_init(&trans, c); bch2_trans_init(&trans, c);
for_each_btree_key(&trans, iter, BTREE_ID_XATTRS, for_each_btree_key(&trans, iter, BTREE_ID_XATTRS,
POS(inum, 0), 0, k) { POS(inum, 0), 0, k, ret) {
BUG_ON(k.k->p.inode < inum); BUG_ON(k.k->p.inode < inum);
if (k.k->p.inode > inum) if (k.k->p.inode > inum)
...@@ -289,27 +289,24 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) ...@@ -289,27 +289,24 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
if (k.k->type != KEY_TYPE_xattr) if (k.k->type != KEY_TYPE_xattr)
continue; continue;
bch2_xattr_emit(dentry, bkey_s_c_to_xattr(k).v, ret = bch2_xattr_emit(dentry, bkey_s_c_to_xattr(k).v, &buf);
&buffer, &buffer_size, &ret); if (ret)
if (ret < 0)
break; break;
} }
bch2_trans_exit(&trans); ret = bch2_trans_exit(&trans) ?: ret;
if (ret < 0) if (ret)
return ret; return ret;
bch2_xattr_list_bcachefs(c, inode, &buffer, ret = bch2_xattr_list_bcachefs(c, inode, &buf, false);
&buffer_size, &ret, false); if (ret)
if (ret < 0)
return ret; return ret;
bch2_xattr_list_bcachefs(c, inode, &buffer, ret = bch2_xattr_list_bcachefs(c, inode, &buf, true);
&buffer_size, &ret, true); if (ret)
if (ret < 0)
return ret; return ret;
return ret; return buf.used;
} }
static int bch2_xattr_get_handler(const struct xattr_handler *handler, static int bch2_xattr_get_handler(const struct xattr_handler *handler,
......
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