@@ -149,6 +149,22 @@ static inline bool xfs_log_dinode_has_large_extent_counts(
149149 (ld -> di_flags2 & XFS_DIFLAG2_NREXT64 );
150150}
151151
152+ static inline void
153+ xfs_log_dinode_to_disk_iext_counters (
154+ struct xfs_log_dinode * from ,
155+ struct xfs_dinode * to )
156+ {
157+ if (xfs_log_dinode_has_large_extent_counts (from )) {
158+ to -> di_big_nextents = cpu_to_be64 (from -> di_big_nextents );
159+ to -> di_big_anextents = cpu_to_be32 (from -> di_big_anextents );
160+ to -> di_nrext64_pad = cpu_to_be16 (from -> di_nrext64_pad );
161+ } else {
162+ to -> di_nextents = cpu_to_be32 (from -> di_nextents );
163+ to -> di_anextents = cpu_to_be16 (from -> di_anextents );
164+ }
165+
166+ }
167+
152168STATIC void
153169xfs_log_dinode_to_disk (
154170 struct xfs_log_dinode * from ,
@@ -165,7 +181,6 @@ xfs_log_dinode_to_disk(
165181 to -> di_nlink = cpu_to_be32 (from -> di_nlink );
166182 to -> di_projid_lo = cpu_to_be16 (from -> di_projid_lo );
167183 to -> di_projid_hi = cpu_to_be16 (from -> di_projid_hi );
168- memcpy (to -> di_pad , from -> di_pad , sizeof (to -> di_pad ));
169184
170185 to -> di_atime = xfs_log_dinode_to_disk_ts (from , from -> di_atime );
171186 to -> di_mtime = xfs_log_dinode_to_disk_ts (from , from -> di_mtime );
@@ -174,8 +189,6 @@ xfs_log_dinode_to_disk(
174189 to -> di_size = cpu_to_be64 (from -> di_size );
175190 to -> di_nblocks = cpu_to_be64 (from -> di_nblocks );
176191 to -> di_extsize = cpu_to_be32 (from -> di_extsize );
177- to -> di_nextents = cpu_to_be32 (from -> di_nextents );
178- to -> di_anextents = cpu_to_be16 (from -> di_anextents );
179192 to -> di_forkoff = from -> di_forkoff ;
180193 to -> di_aformat = from -> di_aformat ;
181194 to -> di_dmevmask = cpu_to_be32 (from -> di_dmevmask );
@@ -191,12 +204,66 @@ xfs_log_dinode_to_disk(
191204 to -> di_cowextsize = cpu_to_be32 (from -> di_cowextsize );
192205 to -> di_ino = cpu_to_be64 (from -> di_ino );
193206 to -> di_lsn = cpu_to_be64 (lsn );
194- memcpy (to -> di_pad2 , from -> di_pad2 , sizeof (to -> di_pad2 ));
207+ memset (to -> di_pad2 , 0 , sizeof (to -> di_pad2 ));
195208 uuid_copy (& to -> di_uuid , & from -> di_uuid );
196- to -> di_flushiter = 0 ;
209+ to -> di_v3_pad = 0 ;
197210 } else {
198211 to -> di_flushiter = cpu_to_be16 (from -> di_flushiter );
212+ memset (to -> di_v2_pad , 0 , sizeof (to -> di_v2_pad ));
213+ }
214+
215+ xfs_log_dinode_to_disk_iext_counters (from , to );
216+ }
217+
218+ STATIC int
219+ xlog_dinode_verify_extent_counts (
220+ struct xfs_mount * mp ,
221+ struct xfs_log_dinode * ldip )
222+ {
223+ xfs_extnum_t nextents ;
224+ xfs_aextnum_t anextents ;
225+
226+ if (xfs_log_dinode_has_large_extent_counts (ldip )) {
227+ if (!xfs_has_large_extent_counts (mp ) ||
228+ (ldip -> di_nrext64_pad != 0 )) {
229+ XFS_CORRUPTION_ERROR (
230+ "Bad log dinode large extent count format" ,
231+ XFS_ERRLEVEL_LOW , mp , ldip , sizeof (* ldip ));
232+ xfs_alert (mp ,
233+ "Bad inode 0x%llx, large extent counts %d, padding 0x%x" ,
234+ ldip -> di_ino , xfs_has_large_extent_counts (mp ),
235+ ldip -> di_nrext64_pad );
236+ return - EFSCORRUPTED ;
237+ }
238+
239+ nextents = ldip -> di_big_nextents ;
240+ anextents = ldip -> di_big_anextents ;
241+ } else {
242+ if (ldip -> di_version == 3 && ldip -> di_v3_pad != 0 ) {
243+ XFS_CORRUPTION_ERROR (
244+ "Bad log dinode di_v3_pad" ,
245+ XFS_ERRLEVEL_LOW , mp , ldip , sizeof (* ldip ));
246+ xfs_alert (mp ,
247+ "Bad inode 0x%llx, di_v3_pad 0x%llx" ,
248+ ldip -> di_ino , ldip -> di_v3_pad );
249+ return - EFSCORRUPTED ;
250+ }
251+
252+ nextents = ldip -> di_nextents ;
253+ anextents = ldip -> di_anextents ;
254+ }
255+
256+ if (unlikely (nextents + anextents > ldip -> di_nblocks )) {
257+ XFS_CORRUPTION_ERROR ("Bad log dinode extent counts" ,
258+ XFS_ERRLEVEL_LOW , mp , ldip , sizeof (* ldip ));
259+ xfs_alert (mp ,
260+ "Bad inode 0x%llx, large extent counts %d, nextents 0x%llx, anextents 0x%x, nblocks 0x%llx" ,
261+ ldip -> di_ino , xfs_has_large_extent_counts (mp ), nextents ,
262+ anextents , ldip -> di_nblocks );
263+ return - EFSCORRUPTED ;
199264 }
265+
266+ return 0 ;
200267}
201268
202269STATIC int
@@ -347,16 +414,11 @@ xlog_recover_inode_commit_pass2(
347414 goto out_release ;
348415 }
349416 }
350- if (unlikely (ldip -> di_nextents + ldip -> di_anextents > ldip -> di_nblocks )){
351- XFS_CORRUPTION_ERROR ("Bad log dinode extent counts" ,
352- XFS_ERRLEVEL_LOW , mp , ldip , sizeof (* ldip ));
353- xfs_alert (mp ,
354- "Bad inode 0x%llx, nextents 0x%x, anextents 0x%x, nblocks 0x%llx" ,
355- in_f -> ilf_ino , ldip -> di_nextents , ldip -> di_anextents ,
356- ldip -> di_nblocks );
357- error = - EFSCORRUPTED ;
417+
418+ error = xlog_dinode_verify_extent_counts (mp , ldip );
419+ if (error )
358420 goto out_release ;
359- }
421+
360422 if (unlikely (ldip -> di_forkoff > mp -> m_sb .sb_inodesize )) {
361423 XFS_CORRUPTION_ERROR ("Bad log dinode fork offset" ,
362424 XFS_ERRLEVEL_LOW , mp , ldip , sizeof (* ldip ));
0 commit comments