Skip to content

Commit 09fb85a

Browse files
author
Kent Overstreet
committed
bcachefs: Run may_delete_deleted_inode() checks in bch2_inode_rm()
We had a bug where bch2_evict_inode() incorrectly called bch2_inode_rm() - the journal clearly showed the inode was not unlinked. We've got checks that we use in recovery when cleaning up deleted inodes, lift them to bch2_inode_rm() as well. Signed-off-by: Kent Overstreet <[email protected]>
1 parent bb6689b commit 09fb85a

File tree

4 files changed

+62
-19
lines changed

4 files changed

+62
-19
lines changed

fs/bcachefs/errcode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@
214214
x(EINVAL, remove_would_lose_data) \
215215
x(EINVAL, no_resize_with_buckets_nouse) \
216216
x(EINVAL, inode_unpack_error) \
217+
x(EINVAL, inode_not_unlinked) \
218+
x(EINVAL, inode_has_child_snapshot) \
217219
x(EINVAL, varint_decode_error) \
218220
x(EINVAL, erasure_coding_found_btree_node) \
219221
x(EINVAL, option_negative) \

fs/bcachefs/fs.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2180,7 +2180,13 @@ static void bch2_evict_inode(struct inode *vinode)
21802180
KEY_TYPE_QUOTA_WARN);
21812181
bch2_quota_acct(c, inode->ei_qid, Q_INO, -1,
21822182
KEY_TYPE_QUOTA_WARN);
2183-
bch2_inode_rm(c, inode_inum(inode));
2183+
int ret = bch2_inode_rm(c, inode_inum(inode));
2184+
if (ret && !bch2_err_matches(ret, EROFS)) {
2185+
bch_err_msg(c, ret, "VFS incorrectly tried to delete inode %llu:%llu",
2186+
inode->ei_inum.subvol,
2187+
inode->ei_inum.inum);
2188+
bch2_sb_error_count(c, BCH_FSCK_ERR_vfs_bad_inode_rm);
2189+
}
21842190

21852191
/*
21862192
* If we are deleting, we need it present in the vfs hash table

fs/bcachefs/inode.c

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ static const char * const bch2_inode_flag_strs[] = {
3838
#undef x
3939

4040
static int delete_ancestor_snapshot_inodes(struct btree_trans *, struct bpos);
41+
static int may_delete_deleted_inum(struct btree_trans *, subvol_inum);
4142

4243
static const u8 byte_table[8] = { 1, 2, 3, 4, 6, 8, 10, 13 };
4344

@@ -1130,19 +1131,23 @@ int bch2_inode_rm(struct bch_fs *c, subvol_inum inum)
11301131
u32 snapshot;
11311132
int ret;
11321133

1134+
ret = lockrestart_do(trans, may_delete_deleted_inum(trans, inum));
1135+
if (ret)
1136+
goto err2;
1137+
11331138
/*
11341139
* If this was a directory, there shouldn't be any real dirents left -
11351140
* but there could be whiteouts (from hash collisions) that we should
11361141
* delete:
11371142
*
1138-
* XXX: the dirent could ideally would delete whiteouts when they're no
1143+
* XXX: the dirent code ideally would delete whiteouts when they're no
11391144
* longer needed
11401145
*/
11411146
ret = bch2_inode_delete_keys(trans, inum, BTREE_ID_extents) ?:
11421147
bch2_inode_delete_keys(trans, inum, BTREE_ID_xattrs) ?:
11431148
bch2_inode_delete_keys(trans, inum, BTREE_ID_dirents);
11441149
if (ret)
1145-
goto err;
1150+
goto err2;
11461151
retry:
11471152
bch2_trans_begin(trans);
11481153

@@ -1392,7 +1397,8 @@ int bch2_inode_rm_snapshot(struct btree_trans *trans, u64 inum, u32 snapshot)
13921397
delete_ancestor_snapshot_inodes(trans, SPOS(0, inum, snapshot));
13931398
}
13941399

1395-
static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
1400+
static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
1401+
bool from_deleted_inodes)
13961402
{
13971403
struct bch_fs *c = trans->c;
13981404
struct btree_iter inode_iter;
@@ -1406,20 +1412,23 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
14061412
if (ret)
14071413
return ret;
14081414

1409-
ret = bkey_is_inode(k.k) ? 0 : -BCH_ERR_ENOENT_inode;
1410-
if (fsck_err_on(!bkey_is_inode(k.k),
1415+
ret = bkey_is_inode(k.k) ? 0 : bch_err_throw(c, ENOENT_inode);
1416+
if (fsck_err_on(from_deleted_inodes && ret,
14111417
trans, deleted_inode_missing,
14121418
"nonexistent inode %llu:%u in deleted_inodes btree",
14131419
pos.offset, pos.snapshot))
14141420
goto delete;
1421+
if (ret)
1422+
goto out;
14151423

14161424
ret = bch2_inode_unpack(k, &inode);
14171425
if (ret)
14181426
goto out;
14191427

14201428
if (S_ISDIR(inode.bi_mode)) {
14211429
ret = bch2_empty_dir_snapshot(trans, pos.offset, 0, pos.snapshot);
1422-
if (fsck_err_on(bch2_err_matches(ret, ENOTEMPTY),
1430+
if (fsck_err_on(from_deleted_inodes &&
1431+
bch2_err_matches(ret, ENOTEMPTY),
14231432
trans, deleted_inode_is_dir,
14241433
"non empty directory %llu:%u in deleted_inodes btree",
14251434
pos.offset, pos.snapshot))
@@ -1428,17 +1437,25 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
14281437
goto out;
14291438
}
14301439

1431-
if (fsck_err_on(!(inode.bi_flags & BCH_INODE_unlinked),
1440+
ret = inode.bi_flags & BCH_INODE_unlinked ? 0 : bch_err_throw(c, inode_not_unlinked);
1441+
if (fsck_err_on(from_deleted_inodes && ret,
14321442
trans, deleted_inode_not_unlinked,
14331443
"non-deleted inode %llu:%u in deleted_inodes btree",
14341444
pos.offset, pos.snapshot))
14351445
goto delete;
1446+
if (ret)
1447+
goto out;
1448+
1449+
ret = !(inode.bi_flags & BCH_INODE_has_child_snapshot)
1450+
? 0 : bch_err_throw(c, inode_has_child_snapshot);
14361451

1437-
if (fsck_err_on(inode.bi_flags & BCH_INODE_has_child_snapshot,
1452+
if (fsck_err_on(from_deleted_inodes && ret,
14381453
trans, deleted_inode_has_child_snapshots,
14391454
"inode with child snapshots %llu:%u in deleted_inodes btree",
14401455
pos.offset, pos.snapshot))
14411456
goto delete;
1457+
if (ret)
1458+
goto out;
14421459

14431460
ret = bch2_inode_has_child_snapshots(trans, k.k->p);
14441461
if (ret < 0)
@@ -1455,19 +1472,28 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
14551472
if (ret)
14561473
goto out;
14571474
}
1475+
1476+
if (!from_deleted_inodes) {
1477+
ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
1478+
bch_err_throw(c, inode_has_child_snapshot);
1479+
goto out;
1480+
}
1481+
14581482
goto delete;
14591483

14601484
}
14611485

1462-
if (test_bit(BCH_FS_clean_recovery, &c->flags) &&
1463-
!fsck_err(trans, deleted_inode_but_clean,
1464-
"filesystem marked as clean but have deleted inode %llu:%u",
1465-
pos.offset, pos.snapshot)) {
1466-
ret = 0;
1467-
goto out;
1468-
}
1486+
if (from_deleted_inodes) {
1487+
if (test_bit(BCH_FS_clean_recovery, &c->flags) &&
1488+
!fsck_err(trans, deleted_inode_but_clean,
1489+
"filesystem marked as clean but have deleted inode %llu:%u",
1490+
pos.offset, pos.snapshot)) {
1491+
ret = 0;
1492+
goto out;
1493+
}
14691494

1470-
ret = 1;
1495+
ret = 1;
1496+
}
14711497
out:
14721498
fsck_err:
14731499
bch2_trans_iter_exit(trans, &inode_iter);
@@ -1478,6 +1504,14 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
14781504
goto out;
14791505
}
14801506

1507+
static int may_delete_deleted_inum(struct btree_trans *trans, subvol_inum inum)
1508+
{
1509+
u32 snapshot;
1510+
1511+
return bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot) ?:
1512+
may_delete_deleted_inode(trans, SPOS(0, inum.inum, snapshot), false);
1513+
}
1514+
14811515
int bch2_delete_dead_inodes(struct bch_fs *c)
14821516
{
14831517
struct btree_trans *trans = bch2_trans_get(c);
@@ -1501,7 +1535,7 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
15011535
ret = for_each_btree_key_commit(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
15021536
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
15031537
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
1504-
ret = may_delete_deleted_inode(trans, k.k->p);
1538+
ret = may_delete_deleted_inode(trans, k.k->p, true);
15051539
if (ret > 0) {
15061540
bch_verbose_ratelimited(c, "deleting unlinked inode %llu:%u",
15071541
k.k->p.offset, k.k->p.snapshot);

fs/bcachefs/sb-errors_format.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ enum bch_fsck_flags {
244244
x(inode_parent_has_case_insensitive_not_set, 317, FSCK_AUTOFIX) \
245245
x(vfs_inode_i_blocks_underflow, 311, FSCK_AUTOFIX) \
246246
x(vfs_inode_i_blocks_not_zero_at_truncate, 313, FSCK_AUTOFIX) \
247+
x(vfs_bad_inode_rm, 320, 0) \
247248
x(deleted_inode_but_clean, 211, FSCK_AUTOFIX) \
248249
x(deleted_inode_missing, 212, FSCK_AUTOFIX) \
249250
x(deleted_inode_is_dir, 213, FSCK_AUTOFIX) \
@@ -329,7 +330,7 @@ enum bch_fsck_flags {
329330
x(dirent_stray_data_after_cf_name, 305, 0) \
330331
x(rebalance_work_incorrectly_set, 309, FSCK_AUTOFIX) \
331332
x(rebalance_work_incorrectly_unset, 310, FSCK_AUTOFIX) \
332-
x(MAX, 320, 0)
333+
x(MAX, 321, 0)
333334

334335
enum bch_sb_error_id {
335336
#define x(t, n, ...) BCH_FSCK_ERR_##t = n,

0 commit comments

Comments
 (0)