Skip to content

Commit

Permalink
bcachefs: Rework logged op error handling
Browse files Browse the repository at this point in the history
Initially it was thought that we just wanted to ignore errors from
logged op replay, but it turns out we do need to catch -EROFS, or we'll
go into an infinite loop.

Signed-off-by: Kent Overstreet <[email protected]>
  • Loading branch information
Kent Overstreet committed Oct 5, 2024
1 parent 1f73cb4 commit 0f25eb4
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 28 deletions.
63 changes: 43 additions & 20 deletions fs/bcachefs/io_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,14 @@ void bch2_logged_op_truncate_to_text(struct printbuf *out, struct bch_fs *c, str

static int truncate_set_isize(struct btree_trans *trans,
subvol_inum inum,
u64 new_i_size)
u64 new_i_size,
bool warn)
{
struct btree_iter iter = { NULL };
struct bch_inode_unpacked inode_u;
int ret;

ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent) ?:
ret = __bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent, warn) ?:
(inode_u.bi_size = new_i_size, 0) ?:
bch2_inode_write(trans, &iter, &inode_u);

Expand All @@ -247,10 +248,11 @@ static int __bch2_resume_logged_op_truncate(struct btree_trans *trans,
struct bkey_i_logged_op_truncate *op = bkey_i_to_logged_op_truncate(op_k);
subvol_inum inum = { le32_to_cpu(op->v.subvol), le64_to_cpu(op->v.inum) };
u64 new_i_size = le64_to_cpu(op->v.new_i_size);
bool warn_errors = i_sectors_delta != NULL;
int ret;

ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
truncate_set_isize(trans, inum, new_i_size));
truncate_set_isize(trans, inum, new_i_size, i_sectors_delta != NULL));
if (ret)
goto err;

Expand All @@ -263,8 +265,8 @@ static int __bch2_resume_logged_op_truncate(struct btree_trans *trans,
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
ret = 0;
err:
bch2_logged_op_finish(trans, op_k);
bch_err_fn(c, ret);
if (warn_errors)
bch_err_fn(c, ret);
return ret;
}

Expand All @@ -288,9 +290,14 @@ int bch2_truncate(struct bch_fs *c, subvol_inum inum, u64 new_i_size, u64 *i_sec
* resume only proceeding in one of the snapshots
*/
down_read(&c->snapshot_create_lock);
int ret = bch2_trans_run(c,
bch2_logged_op_start(trans, &op.k_i) ?:
__bch2_resume_logged_op_truncate(trans, &op.k_i, i_sectors_delta));
struct btree_trans *trans = bch2_trans_get(c);
int ret = bch2_logged_op_start(trans, &op.k_i);
if (ret)
goto out;
ret = __bch2_resume_logged_op_truncate(trans, &op.k_i, i_sectors_delta);
ret = bch2_logged_op_finish(trans, &op.k_i) ?: ret;
out:
bch2_trans_put(trans);
up_read(&c->snapshot_create_lock);

return ret;
Expand All @@ -308,7 +315,8 @@ void bch2_logged_op_finsert_to_text(struct printbuf *out, struct bch_fs *c, stru
prt_printf(out, " src_offset=%llu", le64_to_cpu(op.v->src_offset));
}

static int adjust_i_size(struct btree_trans *trans, subvol_inum inum, u64 offset, s64 len)
static int adjust_i_size(struct btree_trans *trans, subvol_inum inum,
u64 offset, s64 len, bool warn)
{
struct btree_iter iter;
struct bch_inode_unpacked inode_u;
Expand All @@ -317,7 +325,7 @@ static int adjust_i_size(struct btree_trans *trans, subvol_inum inum, u64 offset
offset <<= 9;
len <<= 9;

ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent);
ret = __bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent, warn);
if (ret)
return ret;

Expand Down Expand Up @@ -357,12 +365,22 @@ static int __bch2_resume_logged_op_finsert(struct btree_trans *trans,
u64 len = abs(shift);
u64 pos = le64_to_cpu(op->v.pos);
bool insert = shift > 0;
u32 snapshot;
bool warn_errors = i_sectors_delta != NULL;
int ret = 0;

ret = bch2_inum_opts_get(trans, inum, &opts);
if (ret)
return ret;

/*
* check for missing subvolume before fpunch, as in resume we don't want
* it to be a fatal error
*/
ret = __bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot, warn_errors);
if (ret)
return ret;

bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
POS(inum.inum, 0),
BTREE_ITER_intent);
Expand All @@ -373,7 +391,7 @@ case LOGGED_OP_FINSERT_start:

if (insert) {
ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
adjust_i_size(trans, inum, src_offset, len) ?:
adjust_i_size(trans, inum, src_offset, len, warn_errors) ?:
bch2_logged_op_update(trans, &op->k_i));
if (ret)
goto err;
Expand All @@ -396,11 +414,11 @@ case LOGGED_OP_FINSERT_shift_extents:
struct bkey_i delete, *copy;
struct bkey_s_c k;
struct bpos src_pos = POS(inum.inum, src_offset);
u32 snapshot;

bch2_trans_begin(trans);

ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
ret = __bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot,
warn_errors);
if (ret)
goto btree_err;

Expand Down Expand Up @@ -463,12 +481,12 @@ case LOGGED_OP_FINSERT_shift_extents:

if (!insert) {
ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
adjust_i_size(trans, inum, src_offset, shift) ?:
adjust_i_size(trans, inum, src_offset, shift, warn_errors) ?:
bch2_logged_op_update(trans, &op->k_i));
} else {
/* We need an inode update to update bi_journal_seq for fsync: */
ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
adjust_i_size(trans, inum, 0, 0) ?:
adjust_i_size(trans, inum, 0, 0, warn_errors) ?:
bch2_logged_op_update(trans, &op->k_i));
}

Expand All @@ -477,9 +495,9 @@ case LOGGED_OP_FINSERT_finish:
break;
}
err:
bch_err_fn(c, ret);
bch2_logged_op_finish(trans, op_k);
bch2_trans_iter_exit(trans, &iter);
if (warn_errors)
bch_err_fn(c, ret);
return ret;
}

Expand Down Expand Up @@ -508,9 +526,14 @@ int bch2_fcollapse_finsert(struct bch_fs *c, subvol_inum inum,
* resume only proceeding in one of the snapshots
*/
down_read(&c->snapshot_create_lock);
int ret = bch2_trans_run(c,
bch2_logged_op_start(trans, &op.k_i) ?:
__bch2_resume_logged_op_finsert(trans, &op.k_i, i_sectors_delta));
struct btree_trans *trans = bch2_trans_get(c);
int ret = bch2_logged_op_start(trans, &op.k_i);
if (ret)
goto out;
ret = __bch2_resume_logged_op_finsert(trans, &op.k_i, i_sectors_delta);
ret = bch2_logged_op_finish(trans, &op.k_i) ?: ret;
out:
bch2_trans_put(trans);
up_read(&c->snapshot_create_lock);

return ret;
Expand Down
16 changes: 9 additions & 7 deletions fs/bcachefs/logged_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ static int resume_logged_op(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c k)
{
struct bch_fs *c = trans->c;
const struct bch_logged_op_fn *fn = logged_op_fn(k.k->type);
struct bkey_buf sk;
u32 restart_count = trans->restart_count;
struct printbuf buf = PRINTBUF;
int ret = 0;
Expand All @@ -46,13 +44,15 @@ static int resume_logged_op(struct btree_trans *trans, struct btree_iter *iter,
(bch2_bkey_val_to_text(&buf, c, k),
buf.buf));

if (!fn)
return 0;

struct bkey_buf sk;
bch2_bkey_buf_init(&sk);
bch2_bkey_buf_reassemble(&sk, c, k);

fn->resume(trans, sk.k);
const struct bch_logged_op_fn *fn = logged_op_fn(sk.k->k.type);
if (fn)
fn->resume(trans, sk.k);

ret = bch2_logged_op_finish(trans, sk.k);

bch2_bkey_buf_exit(&sk, c);
fsck_err:
Expand Down Expand Up @@ -93,7 +93,7 @@ int bch2_logged_op_start(struct btree_trans *trans, struct bkey_i *k)
__bch2_logged_op_start(trans, k));
}

void bch2_logged_op_finish(struct btree_trans *trans, struct bkey_i *k)
int bch2_logged_op_finish(struct btree_trans *trans, struct bkey_i *k)
{
int ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
bch2_btree_delete(trans, BTREE_ID_logged_ops, k->k.p, 0));
Expand All @@ -113,4 +113,6 @@ void bch2_logged_op_finish(struct btree_trans *trans, struct bkey_i *k)
buf.buf, bch2_err_str(ret));
printbuf_exit(&buf);
}

return ret;
}
2 changes: 1 addition & 1 deletion fs/bcachefs/logged_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ static inline int bch2_logged_op_update(struct btree_trans *trans, struct bkey_i

int bch2_resume_logged_ops(struct bch_fs *);
int bch2_logged_op_start(struct btree_trans *, struct bkey_i *);
void bch2_logged_op_finish(struct btree_trans *, struct bkey_i *);
int bch2_logged_op_finish(struct btree_trans *, struct bkey_i *);

#endif /* _BCACHEFS_LOGGED_OPS_H */

0 comments on commit 0f25eb4

Please sign in to comment.