@@ -823,6 +823,7 @@ struct inode_walker_entry {
823
823
struct bch_inode_unpacked inode ;
824
824
u32 snapshot ;
825
825
u64 count ;
826
+ u64 i_size ;
826
827
};
827
828
828
829
struct inode_walker {
@@ -910,8 +911,9 @@ lookup_inode_for_snapshot(struct bch_fs *c, struct inode_walker *w, struct bkey_
910
911
if (k .k -> p .snapshot != i -> snapshot && !is_whiteout ) {
911
912
struct inode_walker_entry new = * i ;
912
913
913
- new .snapshot = k .k -> p .snapshot ;
914
- new .count = 0 ;
914
+ new .snapshot = k .k -> p .snapshot ;
915
+ new .count = 0 ;
916
+ new .i_size = 0 ;
915
917
916
918
struct printbuf buf = PRINTBUF ;
917
919
bch2_bkey_val_to_text (& buf , c , k );
@@ -1116,37 +1118,6 @@ static int get_snapshot_root_inode(struct btree_trans *trans,
1116
1118
return ret ;
1117
1119
}
1118
1120
1119
- static int check_directory_size (struct btree_trans * trans ,
1120
- struct bch_inode_unpacked * inode_u ,
1121
- struct bkey_s_c inode_k , bool * write_inode )
1122
- {
1123
- struct btree_iter iter ;
1124
- struct bkey_s_c k ;
1125
- u64 new_size = 0 ;
1126
- int ret ;
1127
-
1128
- for_each_btree_key_max_norestart (trans , iter , BTREE_ID_dirents ,
1129
- SPOS (inode_k .k -> p .offset , 0 , inode_k .k -> p .snapshot ),
1130
- POS (inode_k .k -> p .offset , U64_MAX ),
1131
- 0 , k , ret ) {
1132
- if (k .k -> type != KEY_TYPE_dirent )
1133
- continue ;
1134
-
1135
- struct bkey_s_c_dirent dirent = bkey_s_c_to_dirent (k );
1136
- struct qstr name = bch2_dirent_get_name (dirent );
1137
-
1138
- new_size += dirent_occupied_size (& name );
1139
- }
1140
- bch2_trans_iter_exit (trans , & iter );
1141
-
1142
- if (!ret && inode_u -> bi_size != new_size ) {
1143
- inode_u -> bi_size = new_size ;
1144
- * write_inode = true;
1145
- }
1146
-
1147
- return ret ;
1148
- }
1149
-
1150
1121
static int check_inode (struct btree_trans * trans ,
1151
1122
struct btree_iter * iter ,
1152
1123
struct bkey_s_c k ,
@@ -1335,16 +1306,6 @@ static int check_inode(struct btree_trans *trans,
1335
1306
u .bi_journal_seq = journal_cur_seq (& c -> journal );
1336
1307
do_update = true;
1337
1308
}
1338
-
1339
- if (S_ISDIR (u .bi_mode )) {
1340
- ret = check_directory_size (trans , & u , k , & do_update );
1341
-
1342
- fsck_err_on (ret ,
1343
- trans , directory_size_mismatch ,
1344
- "directory inode %llu:%u with the mismatch directory size" ,
1345
- u .bi_inum , k .k -> p .snapshot );
1346
- ret = 0 ;
1347
- }
1348
1309
do_update :
1349
1310
if (do_update ) {
1350
1311
ret = __bch2_fsck_write_inode (trans , & u );
@@ -2017,10 +1978,31 @@ static int check_subdir_count_notnested(struct btree_trans *trans, struct inode_
2017
1978
return ret ;
2018
1979
}
2019
1980
2020
- static int check_subdir_count (struct btree_trans * trans , struct inode_walker * w )
1981
+ static int check_dir_i_size_notnested (struct btree_trans * trans , struct inode_walker * w )
1982
+ {
1983
+ struct bch_fs * c = trans -> c ;
1984
+ int ret = 0 ;
1985
+
1986
+ darray_for_each (w -> inodes , i )
1987
+ if (fsck_err_on (i -> inode .bi_size != i -> i_size ,
1988
+ trans , inode_dir_wrong_nlink ,
1989
+ "directory %llu:%u with wrong i_size: got %llu, should be %llu" ,
1990
+ w -> last_pos .inode , i -> snapshot , i -> inode .bi_size , i -> i_size )) {
1991
+ i -> inode .bi_size = i -> i_size ;
1992
+ ret = bch2_fsck_write_inode (trans , & i -> inode );
1993
+ if (ret )
1994
+ break ;
1995
+ }
1996
+ fsck_err :
1997
+ bch_err_fn (c , ret );
1998
+ return ret ;
1999
+ }
2000
+
2001
+ static int check_subdir_dirents_count (struct btree_trans * trans , struct inode_walker * w )
2021
2002
{
2022
2003
u32 restart_count = trans -> restart_count ;
2023
2004
return check_subdir_count_notnested (trans , w ) ?:
2005
+ check_dir_i_size_notnested (trans , w ) ?:
2024
2006
trans_was_restarted (trans , restart_count );
2025
2007
}
2026
2008
@@ -2367,7 +2349,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
2367
2349
goto out ;
2368
2350
2369
2351
if (dir -> last_pos .inode != k .k -> p .inode && dir -> have_inodes ) {
2370
- ret = check_subdir_count (trans , dir );
2352
+ ret = check_subdir_dirents_count (trans , dir );
2371
2353
if (ret )
2372
2354
goto err ;
2373
2355
}
@@ -2457,9 +2439,11 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
2457
2439
if (ret )
2458
2440
goto err ;
2459
2441
2460
- if ( d . v -> d_type == DT_DIR )
2461
- for_each_visible_inode ( c , s , dir , d . k -> p . snapshot , i )
2442
+ for_each_visible_inode ( c , s , dir , d . k -> p . snapshot , i ) {
2443
+ if ( d . v -> d_type == DT_DIR )
2462
2444
i -> count ++ ;
2445
+ i -> i_size += bkey_bytes (d .k );
2446
+ }
2463
2447
out :
2464
2448
err :
2465
2449
fsck_err :
0 commit comments