@@ -459,6 +459,33 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub
459
459
return 0 ;
460
460
}
461
461
462
+ static int reconstruct_inode (struct btree_trans * trans , u32 snapshot , u64 inum , u64 size , unsigned mode )
463
+ {
464
+ struct bch_fs * c = trans -> c ;
465
+ struct bch_inode_unpacked new_inode ;
466
+
467
+ bch2_inode_init_early (c , & new_inode );
468
+ bch2_inode_init_late (& new_inode , bch2_current_time (c ), 0 , 0 , mode |0755 , 0 , NULL );
469
+ new_inode .bi_size = size ;
470
+ new_inode .bi_inum = inum ;
471
+
472
+ return __bch2_fsck_write_inode (trans , & new_inode , snapshot );
473
+ }
474
+
475
+ static int reconstruct_reg_inode (struct btree_trans * trans , u32 snapshot , u64 inum )
476
+ {
477
+ struct btree_iter iter = {};
478
+
479
+ bch2_trans_iter_init (trans , & iter , BTREE_ID_extents , SPOS (inum , U64_MAX , snapshot ), 0 );
480
+ struct bkey_s_c k = bch2_btree_iter_peek_prev (& iter );
481
+ bch2_trans_iter_exit (trans , & iter );
482
+ int ret = bkey_err (k );
483
+ if (ret )
484
+ return ret ;
485
+
486
+ return reconstruct_inode (trans , snapshot , inum , k .k -> p .offset << 9 , S_IFREG );
487
+ }
488
+
462
489
struct snapshots_seen_entry {
463
490
u32 id ;
464
491
u32 equiv ;
@@ -1535,6 +1562,17 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
1535
1562
goto err ;
1536
1563
1537
1564
if (k .k -> type != KEY_TYPE_whiteout ) {
1565
+ if (!i && (c -> sb .btrees_lost_data & BIT_ULL (BTREE_ID_inodes ))) {
1566
+ ret = reconstruct_reg_inode (trans , k .k -> p .snapshot , k .k -> p .inode ) ?:
1567
+ bch2_trans_commit (trans , NULL , NULL , BCH_TRANS_COMMIT_no_enospc );
1568
+ if (ret )
1569
+ goto err ;
1570
+
1571
+ inode -> last_pos .inode -- ;
1572
+ ret = - BCH_ERR_transaction_restart_nested ;
1573
+ goto err ;
1574
+ }
1575
+
1538
1576
if (fsck_err_on (!i , c , extent_in_missing_inode ,
1539
1577
"extent in missing inode:\n %s" ,
1540
1578
(printbuf_reset (& buf ),
@@ -2012,7 +2050,6 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
2012
2050
struct snapshots_seen * s )
2013
2051
{
2014
2052
struct bch_fs * c = trans -> c ;
2015
- struct bkey_s_c_dirent d ;
2016
2053
struct inode_walker_entry * i ;
2017
2054
struct printbuf buf = PRINTBUF ;
2018
2055
struct bpos equiv ;
@@ -2051,6 +2088,17 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
2051
2088
* hash_info = bch2_hash_info_init (c , & dir -> inodes .data [0 ].inode );
2052
2089
dir -> first_this_inode = false;
2053
2090
2091
+ if (!i && (c -> sb .btrees_lost_data & BIT_ULL (BTREE_ID_inodes ))) {
2092
+ ret = reconstruct_inode (trans , k .k -> p .snapshot , k .k -> p .inode , 0 , S_IFDIR ) ?:
2093
+ bch2_trans_commit (trans , NULL , NULL , BCH_TRANS_COMMIT_no_enospc );
2094
+ if (ret )
2095
+ goto err ;
2096
+
2097
+ dir -> last_pos .inode -- ;
2098
+ ret = - BCH_ERR_transaction_restart_nested ;
2099
+ goto err ;
2100
+ }
2101
+
2054
2102
if (fsck_err_on (!i , c , dirent_in_missing_dir_inode ,
2055
2103
"dirent in nonexisting directory:\n%s" ,
2056
2104
(printbuf_reset (& buf ),
@@ -2085,7 +2133,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
2085
2133
if (k .k -> type != KEY_TYPE_dirent )
2086
2134
goto out ;
2087
2135
2088
- d = bkey_s_c_to_dirent (k );
2136
+ struct bkey_s_c_dirent d = bkey_s_c_to_dirent (k );
2089
2137
2090
2138
if (d .v -> d_type == DT_SUBVOL ) {
2091
2139
ret = check_dirent_to_subvol (trans , iter , d );
0 commit comments