@@ -631,6 +631,7 @@ struct inode_walker_entry {
631631
632632struct inode_walker {
633633 bool first_this_inode ;
634+ bool have_inodes ;
634635 bool recalculate_sums ;
635636 struct bpos last_pos ;
636637
@@ -668,6 +669,12 @@ static int get_inodes_all_snapshots(struct btree_trans *trans,
668669 struct bkey_s_c k ;
669670 int ret ;
670671
672+ /*
673+ * We no longer have inodes for w->last_pos; clear this to avoid
674+ * screwing up check_i_sectors/check_subdir_count if we take a
675+ * transaction restart here:
676+ */
677+ w -> have_inodes = false;
671678 w -> recalculate_sums = false;
672679 w -> inodes .nr = 0 ;
673680
@@ -685,6 +692,7 @@ static int get_inodes_all_snapshots(struct btree_trans *trans,
685692 return ret ;
686693
687694 w -> first_this_inode = true;
695+ w -> have_inodes = true;
688696 return 0 ;
689697}
690698
@@ -1551,10 +1559,10 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
15511559 struct bkey_s_c k ,
15521560 struct inode_walker * inode ,
15531561 struct snapshots_seen * s ,
1554- struct extent_ends * extent_ends )
1562+ struct extent_ends * extent_ends ,
1563+ struct disk_reservation * res )
15551564{
15561565 struct bch_fs * c = trans -> c ;
1557- struct inode_walker_entry * i ;
15581566 struct printbuf buf = PRINTBUF ;
15591567 int ret = 0 ;
15601568
@@ -1564,7 +1572,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
15641572 goto out ;
15651573 }
15661574
1567- if (inode -> last_pos .inode != k .k -> p .inode ) {
1575+ if (inode -> last_pos .inode != k .k -> p .inode && inode -> have_inodes ) {
15681576 ret = check_i_sectors (trans , inode );
15691577 if (ret )
15701578 goto err ;
@@ -1574,12 +1582,12 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
15741582 if (ret )
15751583 goto err ;
15761584
1577- i = walk_inode (trans , inode , k );
1578- ret = PTR_ERR_OR_ZERO (i );
1585+ struct inode_walker_entry * extent_i = walk_inode (trans , inode , k );
1586+ ret = PTR_ERR_OR_ZERO (extent_i );
15791587 if (ret )
15801588 goto err ;
15811589
1582- ret = check_key_has_inode (trans , iter , inode , i , k );
1590+ ret = check_key_has_inode (trans , iter , inode , extent_i , k );
15831591 if (ret )
15841592 goto err ;
15851593
@@ -1588,24 +1596,19 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
15881596 & inode -> recalculate_sums );
15891597 if (ret )
15901598 goto err ;
1591- }
1592-
1593- /*
1594- * Check inodes in reverse order, from oldest snapshots to newest,
1595- * starting from the inode that matches this extent's snapshot. If we
1596- * didn't have one, iterate over all inodes:
1597- */
1598- if (!i )
1599- i = & darray_last (inode -> inodes );
16001599
1601- for (;
1602- inode -> inodes .data && i >= inode -> inodes .data ;
1603- -- i ) {
1604- if (i -> snapshot > k .k -> p .snapshot ||
1605- !key_visible_in_snapshot (c , s , i -> snapshot , k .k -> p .snapshot ))
1606- continue ;
1600+ /*
1601+ * Check inodes in reverse order, from oldest snapshots to
1602+ * newest, starting from the inode that matches this extent's
1603+ * snapshot. If we didn't have one, iterate over all inodes:
1604+ */
1605+ for (struct inode_walker_entry * i = extent_i ?: & darray_last (inode -> inodes );
1606+ inode -> inodes .data && i >= inode -> inodes .data ;
1607+ -- i ) {
1608+ if (i -> snapshot > k .k -> p .snapshot ||
1609+ !key_visible_in_snapshot (c , s , i -> snapshot , k .k -> p .snapshot ))
1610+ continue ;
16071611
1608- if (k .k -> type != KEY_TYPE_whiteout ) {
16091612 if (fsck_err_on (!(i -> inode .bi_flags & BCH_INODE_i_size_dirty ) &&
16101613 k .k -> p .offset > round_up (i -> inode .bi_size , block_bytes (c )) >> 9 &&
16111614 !bkey_extent_is_reservation (k ),
@@ -1625,10 +1628,24 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
16251628 goto err ;
16261629
16271630 iter -> k .type = KEY_TYPE_whiteout ;
1631+ break ;
16281632 }
1633+ }
1634+ }
1635+
1636+ ret = bch2_trans_commit (trans , res , NULL , BCH_TRANS_COMMIT_no_enospc );
1637+ if (ret )
1638+ goto err ;
1639+
1640+ if (bkey_extent_is_allocation (k .k )) {
1641+ for (struct inode_walker_entry * i = extent_i ?: & darray_last (inode -> inodes );
1642+ inode -> inodes .data && i >= inode -> inodes .data ;
1643+ -- i ) {
1644+ if (i -> snapshot > k .k -> p .snapshot ||
1645+ !key_visible_in_snapshot (c , s , i -> snapshot , k .k -> p .snapshot ))
1646+ continue ;
16291647
1630- if (bkey_extent_is_allocation (k .k ))
1631- i -> count += k .k -> size ;
1648+ i -> count += k .k -> size ;
16321649 }
16331650 }
16341651
@@ -1660,13 +1677,11 @@ int bch2_check_extents(struct bch_fs *c)
16601677 extent_ends_init (& extent_ends );
16611678
16621679 int ret = bch2_trans_run (c ,
1663- for_each_btree_key_commit (trans , iter , BTREE_ID_extents ,
1680+ for_each_btree_key (trans , iter , BTREE_ID_extents ,
16641681 POS (BCACHEFS_ROOT_INO , 0 ),
1665- BTREE_ITER_prefetch |BTREE_ITER_all_snapshots , k ,
1666- & res , NULL ,
1667- BCH_TRANS_COMMIT_no_enospc , ({
1682+ BTREE_ITER_prefetch |BTREE_ITER_all_snapshots , k , ({
16681683 bch2_disk_reservation_put (c , & res );
1669- check_extent (trans , & iter , k , & w , & s , & extent_ends ) ?:
1684+ check_extent (trans , & iter , k , & w , & s , & extent_ends , & res ) ?:
16701685 check_extent_overbig (trans , & iter , k );
16711686 })) ?:
16721687 check_i_sectors_notnested (trans , & w ));
@@ -2068,7 +2083,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
20682083 if (k .k -> type == KEY_TYPE_whiteout )
20692084 goto out ;
20702085
2071- if (dir -> last_pos .inode != k .k -> p .inode ) {
2086+ if (dir -> last_pos .inode != k .k -> p .inode && dir -> have_inodes ) {
20722087 ret = check_subdir_count (trans , dir );
20732088 if (ret )
20742089 goto err ;
@@ -2130,11 +2145,15 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
21302145 if (ret )
21312146 goto err ;
21322147 }
2133-
2134- if (d .v -> d_type == DT_DIR )
2135- for_each_visible_inode (c , s , dir , d .k -> p .snapshot , i )
2136- i -> count ++ ;
21372148 }
2149+
2150+ ret = bch2_trans_commit (trans , NULL , NULL , BCH_TRANS_COMMIT_no_enospc );
2151+ if (ret )
2152+ goto err ;
2153+
2154+ if (d .v -> d_type == DT_DIR )
2155+ for_each_visible_inode (c , s , dir , d .k -> p .snapshot , i )
2156+ i -> count ++ ;
21382157out :
21392158err :
21402159fsck_err :
@@ -2157,12 +2176,9 @@ int bch2_check_dirents(struct bch_fs *c)
21572176 snapshots_seen_init (& s );
21582177
21592178 int ret = bch2_trans_run (c ,
2160- for_each_btree_key_commit (trans , iter , BTREE_ID_dirents ,
2179+ for_each_btree_key (trans , iter , BTREE_ID_dirents ,
21612180 POS (BCACHEFS_ROOT_INO , 0 ),
2162- BTREE_ITER_prefetch |BTREE_ITER_all_snapshots ,
2163- k ,
2164- NULL , NULL ,
2165- BCH_TRANS_COMMIT_no_enospc ,
2181+ BTREE_ITER_prefetch |BTREE_ITER_all_snapshots , k ,
21662182 check_dirent (trans , & iter , k , & hash_info , & dir , & target , & s )) ?:
21672183 check_subdir_count_notnested (trans , & dir ));
21682184
0 commit comments