Skip to content

Commit fd65378

Browse files
author
Kent Overstreet
committed
bcachefs: Don't delete unlinked inodes before logged op resume
Previously, check_inode() would delete unlinked inodes if they weren't on the deleted list - this code dating from before there was a deleted list. But, if we crash during a logged op (truncate or finsert/fcollapse) of an unlinked file, logged op resume will get confused if the inode has already been deleted - instead, just add it to the deleted list if it needs to be there; delete_dead_inodes runs after logged op resume. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 8d65b15 commit fd65378

File tree

4 files changed

+36
-21
lines changed

4 files changed

+36
-21
lines changed

fs/bcachefs/fsck.c

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,26 +1049,39 @@ static int check_inode(struct btree_trans *trans,
10491049
}
10501050

10511051
if (u.bi_flags & BCH_INODE_unlinked) {
1052-
ret = check_inode_deleted_list(trans, k.k->p);
1053-
if (ret < 0)
1054-
return ret;
1052+
if (!test_bit(BCH_FS_started, &c->flags)) {
1053+
/*
1054+
* If we're not in online fsck, don't delete unlinked
1055+
* inodes, just make sure they're on the deleted list.
1056+
*
1057+
* They might be referred to by a logged operation -
1058+
* i.e. we might have crashed in the middle of a
1059+
* truncate on an unlinked but open file - so we want to
1060+
* let the delete_dead_inodes kill it after resuming
1061+
* logged ops.
1062+
*/
1063+
ret = check_inode_deleted_list(trans, k.k->p);
1064+
if (ret < 0)
1065+
return ret;
10551066

1056-
fsck_err_on(!ret,
1057-
trans, unlinked_inode_not_on_deleted_list,
1058-
"inode %llu:%u unlinked, but not on deleted list",
1059-
u.bi_inum, k.k->p.snapshot);
1060-
ret = 0;
1061-
}
1067+
fsck_err_on(!ret,
1068+
trans, unlinked_inode_not_on_deleted_list,
1069+
"inode %llu:%u unlinked, but not on deleted list",
1070+
u.bi_inum, k.k->p.snapshot);
10621071

1063-
if (u.bi_flags & BCH_INODE_unlinked &&
1064-
!bch2_inode_is_open(c, k.k->p) &&
1065-
(!c->sb.clean ||
1066-
fsck_err(trans, inode_unlinked_but_clean,
1067-
"filesystem marked clean, but inode %llu unlinked",
1068-
u.bi_inum))) {
1069-
ret = bch2_inode_rm_snapshot(trans, u.bi_inum, iter->pos.snapshot);
1070-
bch_err_msg(c, ret, "in fsck deleting inode");
1071-
return ret;
1072+
ret = bch2_btree_bit_mod_buffered(trans, BTREE_ID_deleted_inodes, k.k->p, 1);
1073+
if (ret)
1074+
goto err;
1075+
} else {
1076+
if (fsck_err_on(bch2_inode_is_open(c, k.k->p),
1077+
trans, inode_unlinked_and_not_open,
1078+
"inode %llu%u unlinked and not open",
1079+
u.bi_inum, u.bi_snapshot)) {
1080+
ret = bch2_inode_rm_snapshot(trans, u.bi_inum, iter->pos.snapshot);
1081+
bch_err_msg(c, ret, "in fsck deleting inode");
1082+
return ret;
1083+
}
1084+
}
10721085
}
10731086

10741087
if (u.bi_flags & BCH_INODE_i_size_dirty &&

fs/bcachefs/recovery_passes_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
x(check_directory_structure, 30, PASS_ONLINE|PASS_FSCK) \
5151
x(check_nlinks, 31, PASS_FSCK) \
5252
x(resume_logged_ops, 23, PASS_ALWAYS) \
53-
x(delete_dead_inodes, 32, PASS_FSCK|PASS_UNCLEAN) \
53+
x(delete_dead_inodes, 32, PASS_ALWAYS) \
5454
x(fix_reflink_p, 33, 0) \
5555
x(set_fs_needs_rebalance, 34, 0) \
5656

fs/bcachefs/sb-errors_format.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ enum bch_fsck_flags {
210210
x(inode_snapshot_mismatch, 196, 0) \
211211
x(inode_unlinked_but_clean, 197, 0) \
212212
x(inode_unlinked_but_nlink_nonzero, 198, 0) \
213+
x(inode_unlinked_and_not_open, 281, 0) \
213214
x(inode_checksum_type_invalid, 199, 0) \
214215
x(inode_compression_type_invalid, 200, 0) \
215216
x(inode_subvol_root_but_not_dir, 201, 0) \
@@ -292,7 +293,7 @@ enum bch_fsck_flags {
292293
x(accounting_key_replicas_nr_devs_0, 278, FSCK_AUTOFIX) \
293294
x(accounting_key_replicas_nr_required_bad, 279, FSCK_AUTOFIX) \
294295
x(accounting_key_replicas_devs_unsorted, 280, FSCK_AUTOFIX) \
295-
x(MAX, 281, 0)
296+
x(MAX, 282, 0)
296297

297298
enum bch_sb_error_id {
298299
#define x(t, n, ...) BCH_FSCK_ERR_##t = n,

fs/bcachefs/super-io.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,8 @@ static void bch2_sb_ext_to_text(struct printbuf *out, struct bch_sb *sb,
11901190
le_bitvector_to_cpu(errors_silent, (void *) e->errors_silent, sizeof(e->errors_silent) * 8);
11911191

11921192
prt_printf(out, "Errors to silently fix:\t");
1193-
prt_bitflags_vector(out, bch2_sb_error_strs, errors_silent, sizeof(e->errors_silent) * 8);
1193+
prt_bitflags_vector(out, bch2_sb_error_strs, errors_silent,
1194+
min(BCH_FSCK_ERR_MAX, sizeof(e->errors_silent) * 8));
11941195
prt_newline(out);
11951196

11961197
kfree(errors_silent);

0 commit comments

Comments
 (0)