summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-07-22 06:57:05 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:37 -0400
commit0763c552e7ef024ce6dbc9cbc828b8715dff251c (patch)
tree8d4239967ad130502865800b8ba7db8c363c6305
parent91f1b9fdd2c02a7375e46bb2628870f3c6116072 (diff)
downloadlinux-stable-0763c552e7ef024ce6dbc9cbc828b8715dff251c.tar.gz
linux-stable-0763c552e7ef024ce6dbc9cbc828b8715dff251c.tar.bz2
linux-stable-0763c552e7ef024ce6dbc9cbc828b8715dff251c.zip
bcachefs: fsck: Fix nested transaction handling
This uses the new trans->restart count to make sure we always correctly return -BCH_ERR_transaction_restart_nested when we restart a nested transaction - eliminating some other hacks and preparing for new assertions. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/fsck.c43
1 files changed, 23 insertions, 20 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index ea264421fe8f..bb8cab7cb405 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -650,6 +650,7 @@ static int __walk_inode(struct btree_trans *trans,
struct bch_fs *c = trans->c;
struct btree_iter iter;
struct bkey_s_c k;
+ u32 restart_count = trans->restart_count;
unsigned i;
int ret;
@@ -677,6 +678,10 @@ static int __walk_inode(struct btree_trans *trans,
w->cur_inum = pos.inode;
w->first_this_inode = true;
+
+ if (trans_was_restarted(trans, restart_count))
+ return -BCH_ERR_transaction_restart_nested;
+
lookup_snapshot:
for (i = 0; i < w->inodes.nr; i++)
if (bch2_snapshot_is_ancestor(c, pos.snapshot, w->inodes.data[i].snapshot))
@@ -1115,7 +1120,8 @@ static int check_i_sectors(struct btree_trans *trans, struct inode_walker *w)
{
struct bch_fs *c = trans->c;
struct inode_walker_entry *i;
- int ret = 0, ret2 = 0;
+ u32 restart_count = trans->restart_count;
+ int ret = 0;
s64 count2;
darray_for_each(w->inodes, i) {
@@ -1140,13 +1146,16 @@ static int check_i_sectors(struct btree_trans *trans, struct inode_walker *w)
ret = write_inode(trans, &i->inode, i->snapshot);
if (ret)
break;
- ret2 = -BCH_ERR_transaction_restart_nested;
}
}
fsck_err:
- if (ret)
+ if (ret) {
bch_err(c, "error from check_i_sectors(): %s", bch2_err_str(ret));
- return ret ?: ret2;
+ return ret;
+ }
+ if (trans_was_restarted(trans, restart_count))
+ return -BCH_ERR_transaction_restart_nested;
+ return 0;
}
static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
@@ -1182,14 +1191,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
goto err;
}
- if (!iter->path->should_be_locked) {
- /*
- * hack: check_i_sectors may have handled a transaction restart,
- * it shouldn't be but we need to fix the new i_sectors check
- * code and delete the old bch2_count_inode_sectors() first
- */
- return -BCH_ERR_transaction_restart_nested;
- }
+ BUG_ON(!iter->path->should_be_locked);
#if 0
if (bkey_cmp(prev.k->k.p, bkey_start_pos(k.k)) > 0) {
char buf1[200];
@@ -1336,7 +1338,8 @@ static int check_subdir_count(struct btree_trans *trans, struct inode_walker *w)
{
struct bch_fs *c = trans->c;
struct inode_walker_entry *i;
- int ret = 0, ret2 = 0;
+ u32 restart_count = trans->restart_count;
+ int ret = 0;
s64 count2;
darray_for_each(w->inodes, i) {
@@ -1362,13 +1365,16 @@ static int check_subdir_count(struct btree_trans *trans, struct inode_walker *w)
ret = write_inode(trans, &i->inode, i->snapshot);
if (ret)
break;
- ret2 = -BCH_ERR_transaction_restart_nested;
}
}
fsck_err:
- if (ret)
+ if (ret) {
bch_err(c, "error from check_subdir_count(): %s", bch2_err_str(ret));
- return ret ?: ret2;
+ return ret;
+ }
+ if (trans_was_restarted(trans, restart_count))
+ return -BCH_ERR_transaction_restart_nested;
+ return 0;
}
static int check_dirent_target(struct btree_trans *trans,
@@ -1526,10 +1532,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
goto err;
}
- if (!iter->path->should_be_locked) {
- /* hack: see check_extent() */
- return -BCH_ERR_transaction_restart_nested;
- }
+ BUG_ON(!iter->path->should_be_locked);
ret = __walk_inode(trans, dir, equiv);
if (ret < 0)