@@ -631,6 +631,7 @@ struct inode_walker_entry {
631
631
632
632
struct inode_walker {
633
633
bool first_this_inode ;
634
+ bool have_inodes ;
634
635
bool recalculate_sums ;
635
636
struct bpos last_pos ;
636
637
@@ -668,6 +669,12 @@ static int get_inodes_all_snapshots(struct btree_trans *trans,
668
669
struct bkey_s_c k ;
669
670
int ret ;
670
671
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;
671
678
w -> recalculate_sums = false;
672
679
w -> inodes .nr = 0 ;
673
680
@@ -685,6 +692,7 @@ static int get_inodes_all_snapshots(struct btree_trans *trans,
685
692
return ret ;
686
693
687
694
w -> first_this_inode = true;
695
+ w -> have_inodes = true;
688
696
return 0 ;
689
697
}
690
698
@@ -1551,10 +1559,10 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
1551
1559
struct bkey_s_c k ,
1552
1560
struct inode_walker * inode ,
1553
1561
struct snapshots_seen * s ,
1554
- struct extent_ends * extent_ends )
1562
+ struct extent_ends * extent_ends ,
1563
+ struct disk_reservation * res )
1555
1564
{
1556
1565
struct bch_fs * c = trans -> c ;
1557
- struct inode_walker_entry * i ;
1558
1566
struct printbuf buf = PRINTBUF ;
1559
1567
int ret = 0 ;
1560
1568
@@ -1564,7 +1572,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
1564
1572
goto out ;
1565
1573
}
1566
1574
1567
- if (inode -> last_pos .inode != k .k -> p .inode ) {
1575
+ if (inode -> last_pos .inode != k .k -> p .inode && inode -> have_inodes ) {
1568
1576
ret = check_i_sectors (trans , inode );
1569
1577
if (ret )
1570
1578
goto err ;
@@ -1574,12 +1582,12 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
1574
1582
if (ret )
1575
1583
goto err ;
1576
1584
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 );
1579
1587
if (ret )
1580
1588
goto err ;
1581
1589
1582
- ret = check_key_has_inode (trans , iter , inode , i , k );
1590
+ ret = check_key_has_inode (trans , iter , inode , extent_i , k );
1583
1591
if (ret )
1584
1592
goto err ;
1585
1593
@@ -1588,24 +1596,19 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
1588
1596
& inode -> recalculate_sums );
1589
1597
if (ret )
1590
1598
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 );
1600
1599
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 ;
1607
1611
1608
- if (k .k -> type != KEY_TYPE_whiteout ) {
1609
1612
if (fsck_err_on (!(i -> inode .bi_flags & BCH_INODE_i_size_dirty ) &&
1610
1613
k .k -> p .offset > round_up (i -> inode .bi_size , block_bytes (c )) >> 9 &&
1611
1614
!bkey_extent_is_reservation (k ),
@@ -1625,10 +1628,24 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
1625
1628
goto err ;
1626
1629
1627
1630
iter -> k .type = KEY_TYPE_whiteout ;
1631
+ break ;
1628
1632
}
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 ;
1629
1647
1630
- if (bkey_extent_is_allocation (k .k ))
1631
- i -> count += k .k -> size ;
1648
+ i -> count += k .k -> size ;
1632
1649
}
1633
1650
}
1634
1651
@@ -1660,13 +1677,11 @@ int bch2_check_extents(struct bch_fs *c)
1660
1677
extent_ends_init (& extent_ends );
1661
1678
1662
1679
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 ,
1664
1681
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 , ({
1668
1683
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 ) ?:
1670
1685
check_extent_overbig (trans , & iter , k );
1671
1686
})) ?:
1672
1687
check_i_sectors_notnested (trans , & w ));
@@ -2068,7 +2083,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
2068
2083
if (k .k -> type == KEY_TYPE_whiteout )
2069
2084
goto out ;
2070
2085
2071
- if (dir -> last_pos .inode != k .k -> p .inode ) {
2086
+ if (dir -> last_pos .inode != k .k -> p .inode && dir -> have_inodes ) {
2072
2087
ret = check_subdir_count (trans , dir );
2073
2088
if (ret )
2074
2089
goto err ;
@@ -2130,11 +2145,15 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
2130
2145
if (ret )
2131
2146
goto err ;
2132
2147
}
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 ++ ;
2137
2148
}
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 ++ ;
2138
2157
out :
2139
2158
err :
2140
2159
fsck_err :
@@ -2157,12 +2176,9 @@ int bch2_check_dirents(struct bch_fs *c)
2157
2176
snapshots_seen_init (& s );
2158
2177
2159
2178
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 ,
2161
2180
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 ,
2166
2182
check_dirent (trans , & iter , k , & hash_info , & dir , & target , & s )) ?:
2167
2183
check_subdir_count_notnested (trans , & dir ));
2168
2184
0 commit comments