Skip to content

Commit 4bd156c

Browse files
author
Kent Overstreet
committed
bcachefs: Fix bch2_delete_dead_inodes()
- the fsck_err() check for the filesystem being clean was incorrect, causing us to always fail to delete unlinked inodes - if a snapshot had been taken, the unlinked inode needs to be propagated to snapshot leaves so the unlink can happen there - fixed. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 7cb2a78 commit 4bd156c

2 files changed

Lines changed: 69 additions & 22 deletions

File tree

fs/bcachefs/inode.c

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,10 @@ int bch2_inode_peek(struct btree_trans *trans,
362362
return ret;
363363
}
364364

365-
int bch2_inode_write(struct btree_trans *trans,
365+
int bch2_inode_write_flags(struct btree_trans *trans,
366366
struct btree_iter *iter,
367-
struct bch_inode_unpacked *inode)
367+
struct bch_inode_unpacked *inode,
368+
enum btree_update_flags flags)
368369
{
369370
struct bkey_inode_buf *inode_p;
370371

@@ -374,7 +375,7 @@ int bch2_inode_write(struct btree_trans *trans,
374375

375376
bch2_inode_pack_inlined(inode_p, inode);
376377
inode_p->inode.k.p.snapshot = iter->snapshot;
377-
return bch2_trans_update(trans, iter, &inode_p->inode.k_i, 0);
378+
return bch2_trans_update(trans, iter, &inode_p->inode.k_i, flags);
378379
}
379380

380381
struct bkey_i *bch2_inode_to_v3(struct btree_trans *trans, struct bkey_i *k)
@@ -1055,24 +1056,18 @@ int bch2_inode_rm_snapshot(struct btree_trans *trans, u64 inum, u32 snapshot)
10551056
return ret ?: -BCH_ERR_transaction_restart_nested;
10561057
}
10571058

1058-
static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
1059+
static int may_delete_deleted_inode(struct btree_trans *trans,
1060+
struct btree_iter *iter,
1061+
struct bpos pos,
1062+
bool *need_another_pass)
10591063
{
10601064
struct bch_fs *c = trans->c;
1061-
struct btree_iter iter;
1065+
struct btree_iter inode_iter;
10621066
struct bkey_s_c k;
10631067
struct bch_inode_unpacked inode;
10641068
int ret;
10651069

1066-
if (bch2_snapshot_is_internal_node(c, pos.snapshot))
1067-
return 0;
1068-
1069-
if (!fsck_err_on(c->sb.clean, c,
1070-
deleted_inode_but_clean,
1071-
"filesystem marked as clean but have deleted inode %llu:%u",
1072-
pos.offset, pos.snapshot))
1073-
return 0;
1074-
1075-
k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes, pos, BTREE_ITER_CACHED);
1070+
k = bch2_bkey_get_iter(trans, &inode_iter, BTREE_ID_inodes, pos, BTREE_ITER_CACHED);
10761071
ret = bkey_err(k);
10771072
if (ret)
10781073
return ret;
@@ -1086,7 +1081,7 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
10861081

10871082
ret = bch2_inode_unpack(k, &inode);
10881083
if (ret)
1089-
goto err;
1084+
goto out;
10901085

10911086
if (fsck_err_on(S_ISDIR(inode.bi_mode), c,
10921087
deleted_inode_is_dir,
@@ -1100,20 +1095,57 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos)
11001095
pos.offset, pos.snapshot))
11011096
goto delete;
11021097

1103-
return 1;
1104-
err:
1098+
if (c->sb.clean &&
1099+
!fsck_err(c,
1100+
deleted_inode_but_clean,
1101+
"filesystem marked as clean but have deleted inode %llu:%u",
1102+
pos.offset, pos.snapshot)) {
1103+
ret = 0;
1104+
goto out;
1105+
}
1106+
1107+
if (bch2_snapshot_is_internal_node(c, pos.snapshot)) {
1108+
struct bpos new_min_pos;
1109+
1110+
ret = bch2_propagate_key_to_snapshot_leaves(trans, inode_iter.btree_id, k, &new_min_pos);
1111+
if (ret)
1112+
goto out;
1113+
1114+
inode.bi_flags &= ~BCH_INODE_UNLINKED;
1115+
1116+
ret = bch2_inode_write_flags(trans, &inode_iter, &inode,
1117+
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
1118+
bch_err_msg(c, ret, "clearing inode unlinked flag");
1119+
if (ret)
1120+
goto out;
1121+
1122+
/*
1123+
* We'll need another write buffer flush to pick up the new
1124+
* unlinked inodes in the snapshot leaves:
1125+
*/
1126+
*need_another_pass = true;
1127+
return 0;
1128+
}
1129+
1130+
ret = 1;
1131+
out:
11051132
fsck_err:
1133+
bch2_trans_iter_exit(trans, &inode_iter);
11061134
return ret;
11071135
delete:
1108-
return bch2_btree_bit_mod(trans, BTREE_ID_deleted_inodes, pos, false);
1136+
ret = bch2_btree_bit_mod(trans, BTREE_ID_deleted_inodes, pos, false);
1137+
goto out;
11091138
}
11101139

11111140
int bch2_delete_dead_inodes(struct bch_fs *c)
11121141
{
11131142
struct btree_trans *trans = bch2_trans_get(c);
11141143
struct btree_iter iter;
11151144
struct bkey_s_c k;
1145+
bool need_another_pass;
11161146
int ret;
1147+
again:
1148+
need_another_pass = false;
11171149

11181150
ret = bch2_btree_write_buffer_flush_sync(trans);
11191151
if (ret)
@@ -1127,7 +1159,8 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
11271159
*/
11281160
for_each_btree_key(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
11291161
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
1130-
ret = lockrestart_do(trans, may_delete_deleted_inode(trans, k.k->p));
1162+
ret = lockrestart_do(trans, may_delete_deleted_inode(trans, &iter, k.k->p,
1163+
&need_another_pass));
11311164
if (ret < 0)
11321165
break;
11331166

@@ -1137,12 +1170,17 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
11371170
bch2_fs_lazy_rw(c);
11381171
}
11391172

1173+
bch_verbose(c, "deleting unlinked inode %llu:%u", k.k->p.offset, k.k->p.snapshot);
1174+
11401175
ret = bch2_inode_rm_snapshot(trans, k.k->p.offset, k.k->p.snapshot);
11411176
if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
11421177
break;
11431178
}
11441179
}
11451180
bch2_trans_iter_exit(trans, &iter);
1181+
1182+
if (!ret && need_another_pass)
1183+
goto again;
11461184
err:
11471185
bch2_trans_put(trans);
11481186

fs/bcachefs/inode.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#define _BCACHEFS_INODE_H
44

55
#include "bkey.h"
6+
#include "bkey_methods.h"
67
#include "opts.h"
78

89
enum bkey_invalid_flags;
@@ -101,8 +102,16 @@ void bch2_inode_unpacked_to_text(struct printbuf *, struct bch_inode_unpacked *)
101102

102103
int bch2_inode_peek(struct btree_trans *, struct btree_iter *,
103104
struct bch_inode_unpacked *, subvol_inum, unsigned);
104-
int bch2_inode_write(struct btree_trans *, struct btree_iter *,
105-
struct bch_inode_unpacked *);
105+
106+
int bch2_inode_write_flags(struct btree_trans *, struct btree_iter *,
107+
struct bch_inode_unpacked *, enum btree_update_flags);
108+
109+
static inline int bch2_inode_write(struct btree_trans *trans,
110+
struct btree_iter *iter,
111+
struct bch_inode_unpacked *inode)
112+
{
113+
return bch2_inode_write_flags(trans, iter, inode, 0);
114+
}
106115

107116
void bch2_inode_init_early(struct bch_fs *,
108117
struct bch_inode_unpacked *);

0 commit comments

Comments
 (0)