@@ -823,6 +823,7 @@ struct inode_walker_entry {
823823 struct bch_inode_unpacked inode ;
824824 u32 snapshot ;
825825 u64 count ;
826+ u64 i_size ;
826827};
827828
828829struct inode_walker {
@@ -910,8 +911,9 @@ lookup_inode_for_snapshot(struct bch_fs *c, struct inode_walker *w, struct bkey_
910911 if (k .k -> p .snapshot != i -> snapshot && !is_whiteout ) {
911912 struct inode_walker_entry new = * i ;
912913
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 ;
915917
916918 struct printbuf buf = PRINTBUF ;
917919 bch2_bkey_val_to_text (& buf , c , k );
@@ -1116,37 +1118,6 @@ static int get_snapshot_root_inode(struct btree_trans *trans,
11161118 return ret ;
11171119}
11181120
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-
11501121static int check_inode (struct btree_trans * trans ,
11511122 struct btree_iter * iter ,
11521123 struct bkey_s_c k ,
@@ -1335,16 +1306,6 @@ static int check_inode(struct btree_trans *trans,
13351306 u .bi_journal_seq = journal_cur_seq (& c -> journal );
13361307 do_update = true;
13371308 }
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- }
13481309do_update :
13491310 if (do_update ) {
13501311 ret = __bch2_fsck_write_inode (trans , & u );
@@ -2017,10 +1978,31 @@ static int check_subdir_count_notnested(struct btree_trans *trans, struct inode_
20171978 return ret ;
20181979}
20191980
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 )
20212002{
20222003 u32 restart_count = trans -> restart_count ;
20232004 return check_subdir_count_notnested (trans , w ) ?:
2005+ check_dir_i_size_notnested (trans , w ) ?:
20242006 trans_was_restarted (trans , restart_count );
20252007}
20262008
@@ -2367,7 +2349,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
23672349 goto out ;
23682350
23692351 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 );
23712353 if (ret )
23722354 goto err ;
23732355 }
@@ -2457,9 +2439,11 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
24572439 if (ret )
24582440 goto err ;
24592441
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 )
24622444 i -> count ++ ;
2445+ i -> i_size += bkey_bytes (d .k );
2446+ }
24632447out :
24642448err :
24652449fsck_err :
0 commit comments