Skip to content

Commit 0f25eb4

Browse files
author
Kent Overstreet
committed
bcachefs: Rework logged op error handling
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 <kent.overstreet@linux.dev>
1 parent 1f73cb4 commit 0f25eb4

File tree

3 files changed

+53
-28
lines changed

3 files changed

+53
-28
lines changed

fs/bcachefs/io_misc.c

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,14 @@ void bch2_logged_op_truncate_to_text(struct printbuf *out, struct bch_fs *c, str
224224

225225
static int truncate_set_isize(struct btree_trans *trans,
226226
subvol_inum inum,
227-
u64 new_i_size)
227+
u64 new_i_size,
228+
bool warn)
228229
{
229230
struct btree_iter iter = { NULL };
230231
struct bch_inode_unpacked inode_u;
231232
int ret;
232233

233-
ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent) ?:
234+
ret = __bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent, warn) ?:
234235
(inode_u.bi_size = new_i_size, 0) ?:
235236
bch2_inode_write(trans, &iter, &inode_u);
236237

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

252254
ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
253-
truncate_set_isize(trans, inum, new_i_size));
255+
truncate_set_isize(trans, inum, new_i_size, i_sectors_delta != NULL));
254256
if (ret)
255257
goto err;
256258

@@ -263,8 +265,8 @@ static int __bch2_resume_logged_op_truncate(struct btree_trans *trans,
263265
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
264266
ret = 0;
265267
err:
266-
bch2_logged_op_finish(trans, op_k);
267-
bch_err_fn(c, ret);
268+
if (warn_errors)
269+
bch_err_fn(c, ret);
268270
return ret;
269271
}
270272

@@ -288,9 +290,14 @@ int bch2_truncate(struct bch_fs *c, subvol_inum inum, u64 new_i_size, u64 *i_sec
288290
* resume only proceeding in one of the snapshots
289291
*/
290292
down_read(&c->snapshot_create_lock);
291-
int ret = bch2_trans_run(c,
292-
bch2_logged_op_start(trans, &op.k_i) ?:
293-
__bch2_resume_logged_op_truncate(trans, &op.k_i, i_sectors_delta));
293+
struct btree_trans *trans = bch2_trans_get(c);
294+
int ret = bch2_logged_op_start(trans, &op.k_i);
295+
if (ret)
296+
goto out;
297+
ret = __bch2_resume_logged_op_truncate(trans, &op.k_i, i_sectors_delta);
298+
ret = bch2_logged_op_finish(trans, &op.k_i) ?: ret;
299+
out:
300+
bch2_trans_put(trans);
294301
up_read(&c->snapshot_create_lock);
295302

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

311-
static int adjust_i_size(struct btree_trans *trans, subvol_inum inum, u64 offset, s64 len)
318+
static int adjust_i_size(struct btree_trans *trans, subvol_inum inum,
319+
u64 offset, s64 len, bool warn)
312320
{
313321
struct btree_iter iter;
314322
struct bch_inode_unpacked inode_u;
@@ -317,7 +325,7 @@ static int adjust_i_size(struct btree_trans *trans, subvol_inum inum, u64 offset
317325
offset <<= 9;
318326
len <<= 9;
319327

320-
ret = bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent);
328+
ret = __bch2_inode_peek(trans, &iter, &inode_u, inum, BTREE_ITER_intent, warn);
321329
if (ret)
322330
return ret;
323331

@@ -357,12 +365,22 @@ static int __bch2_resume_logged_op_finsert(struct btree_trans *trans,
357365
u64 len = abs(shift);
358366
u64 pos = le64_to_cpu(op->v.pos);
359367
bool insert = shift > 0;
368+
u32 snapshot;
369+
bool warn_errors = i_sectors_delta != NULL;
360370
int ret = 0;
361371

362372
ret = bch2_inum_opts_get(trans, inum, &opts);
363373
if (ret)
364374
return ret;
365375

376+
/*
377+
* check for missing subvolume before fpunch, as in resume we don't want
378+
* it to be a fatal error
379+
*/
380+
ret = __bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot, warn_errors);
381+
if (ret)
382+
return ret;
383+
366384
bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
367385
POS(inum.inum, 0),
368386
BTREE_ITER_intent);
@@ -373,7 +391,7 @@ case LOGGED_OP_FINSERT_start:
373391

374392
if (insert) {
375393
ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
376-
adjust_i_size(trans, inum, src_offset, len) ?:
394+
adjust_i_size(trans, inum, src_offset, len, warn_errors) ?:
377395
bch2_logged_op_update(trans, &op->k_i));
378396
if (ret)
379397
goto err;
@@ -396,11 +414,11 @@ case LOGGED_OP_FINSERT_shift_extents:
396414
struct bkey_i delete, *copy;
397415
struct bkey_s_c k;
398416
struct bpos src_pos = POS(inum.inum, src_offset);
399-
u32 snapshot;
400417

401418
bch2_trans_begin(trans);
402419

403-
ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
420+
ret = __bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot,
421+
warn_errors);
404422
if (ret)
405423
goto btree_err;
406424

@@ -463,12 +481,12 @@ case LOGGED_OP_FINSERT_shift_extents:
463481

464482
if (!insert) {
465483
ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
466-
adjust_i_size(trans, inum, src_offset, shift) ?:
484+
adjust_i_size(trans, inum, src_offset, shift, warn_errors) ?:
467485
bch2_logged_op_update(trans, &op->k_i));
468486
} else {
469487
/* We need an inode update to update bi_journal_seq for fsync: */
470488
ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
471-
adjust_i_size(trans, inum, 0, 0) ?:
489+
adjust_i_size(trans, inum, 0, 0, warn_errors) ?:
472490
bch2_logged_op_update(trans, &op->k_i));
473491
}
474492

@@ -477,9 +495,9 @@ case LOGGED_OP_FINSERT_finish:
477495
break;
478496
}
479497
err:
480-
bch_err_fn(c, ret);
481-
bch2_logged_op_finish(trans, op_k);
482498
bch2_trans_iter_exit(trans, &iter);
499+
if (warn_errors)
500+
bch_err_fn(c, ret);
483501
return ret;
484502
}
485503

@@ -508,9 +526,14 @@ int bch2_fcollapse_finsert(struct bch_fs *c, subvol_inum inum,
508526
* resume only proceeding in one of the snapshots
509527
*/
510528
down_read(&c->snapshot_create_lock);
511-
int ret = bch2_trans_run(c,
512-
bch2_logged_op_start(trans, &op.k_i) ?:
513-
__bch2_resume_logged_op_finsert(trans, &op.k_i, i_sectors_delta));
529+
struct btree_trans *trans = bch2_trans_get(c);
530+
int ret = bch2_logged_op_start(trans, &op.k_i);
531+
if (ret)
532+
goto out;
533+
ret = __bch2_resume_logged_op_finsert(trans, &op.k_i, i_sectors_delta);
534+
ret = bch2_logged_op_finish(trans, &op.k_i) ?: ret;
535+
out:
536+
bch2_trans_put(trans);
514537
up_read(&c->snapshot_create_lock);
515538

516539
return ret;

fs/bcachefs/logged_ops.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ static int resume_logged_op(struct btree_trans *trans, struct btree_iter *iter,
3434
struct bkey_s_c k)
3535
{
3636
struct bch_fs *c = trans->c;
37-
const struct bch_logged_op_fn *fn = logged_op_fn(k.k->type);
38-
struct bkey_buf sk;
3937
u32 restart_count = trans->restart_count;
4038
struct printbuf buf = PRINTBUF;
4139
int ret = 0;
@@ -46,13 +44,15 @@ static int resume_logged_op(struct btree_trans *trans, struct btree_iter *iter,
4644
(bch2_bkey_val_to_text(&buf, c, k),
4745
buf.buf));
4846

49-
if (!fn)
50-
return 0;
51-
47+
struct bkey_buf sk;
5248
bch2_bkey_buf_init(&sk);
5349
bch2_bkey_buf_reassemble(&sk, c, k);
5450

55-
fn->resume(trans, sk.k);
51+
const struct bch_logged_op_fn *fn = logged_op_fn(sk.k->k.type);
52+
if (fn)
53+
fn->resume(trans, sk.k);
54+
55+
ret = bch2_logged_op_finish(trans, sk.k);
5656

5757
bch2_bkey_buf_exit(&sk, c);
5858
fsck_err:
@@ -93,7 +93,7 @@ int bch2_logged_op_start(struct btree_trans *trans, struct bkey_i *k)
9393
__bch2_logged_op_start(trans, k));
9494
}
9595

96-
void bch2_logged_op_finish(struct btree_trans *trans, struct bkey_i *k)
96+
int bch2_logged_op_finish(struct btree_trans *trans, struct bkey_i *k)
9797
{
9898
int ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
9999
bch2_btree_delete(trans, BTREE_ID_logged_ops, k->k.p, 0));
@@ -113,4 +113,6 @@ void bch2_logged_op_finish(struct btree_trans *trans, struct bkey_i *k)
113113
buf.buf, bch2_err_str(ret));
114114
printbuf_exit(&buf);
115115
}
116+
117+
return ret;
116118
}

fs/bcachefs/logged_ops.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ static inline int bch2_logged_op_update(struct btree_trans *trans, struct bkey_i
1515

1616
int bch2_resume_logged_ops(struct bch_fs *);
1717
int bch2_logged_op_start(struct btree_trans *, struct bkey_i *);
18-
void bch2_logged_op_finish(struct btree_trans *, struct bkey_i *);
18+
int bch2_logged_op_finish(struct btree_trans *, struct bkey_i *);
1919

2020
#endif /* _BCACHEFS_LOGGED_OPS_H */

0 commit comments

Comments
 (0)