Skip to content

Commit 7930d9e

Browse files
Dave ChinnerChandan Babu R
authored andcommitted
xfs: recovery should not clear di_flushiter unconditionally
Because on v3 inodes, di_flushiter doesn't exist. It overlaps with zero padding in the inode, except when NREXT64=1 configurations are in use and the zero padding is no longer padding but holds the 64 bit extent counter. This manifests obviously on big endian platforms (e.g. s390) because the log dinode is in host order and the overlap is the LSBs of the extent count field. It is not noticed on little endian machines because the overlap is at the MSB end of the extent count field and we need to get more than 2^^48 extents in the inode before it manifests. i.e. the heat death of the universe will occur before we see the problem in little endian machines. This is a zero-day issue for NREXT64=1 configuraitons on big endian machines. Fix it by only clearing di_flushiter on v2 inodes during recovery. Fixes: 9b7d16e ("xfs: Introduce XFS_DIFLAG2_NREXT64 and associated helpers") cc: stable@kernel.org # 5.19+ Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
1 parent 038ca18 commit 7930d9e

File tree

1 file changed

+17
-15
lines changed

1 file changed

+17
-15
lines changed

fs/xfs/xfs_inode_item_recover.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -370,24 +370,26 @@ xlog_recover_inode_commit_pass2(
370370
* superblock flag to determine whether we need to look at di_flushiter
371371
* to skip replay when the on disk inode is newer than the log one
372372
*/
373-
if (!xfs_has_v3inodes(mp) &&
374-
ldip->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
375-
/*
376-
* Deal with the wrap case, DI_MAX_FLUSH is less
377-
* than smaller numbers
378-
*/
379-
if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH &&
380-
ldip->di_flushiter < (DI_MAX_FLUSH >> 1)) {
381-
/* do nothing */
382-
} else {
383-
trace_xfs_log_recover_inode_skip(log, in_f);
384-
error = 0;
385-
goto out_release;
373+
if (!xfs_has_v3inodes(mp)) {
374+
if (ldip->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
375+
/*
376+
* Deal with the wrap case, DI_MAX_FLUSH is less
377+
* than smaller numbers
378+
*/
379+
if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH &&
380+
ldip->di_flushiter < (DI_MAX_FLUSH >> 1)) {
381+
/* do nothing */
382+
} else {
383+
trace_xfs_log_recover_inode_skip(log, in_f);
384+
error = 0;
385+
goto out_release;
386+
}
386387
}
388+
389+
/* Take the opportunity to reset the flush iteration count */
390+
ldip->di_flushiter = 0;
387391
}
388392

389-
/* Take the opportunity to reset the flush iteration count */
390-
ldip->di_flushiter = 0;
391393

392394
if (unlikely(S_ISREG(ldip->di_mode))) {
393395
if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&

0 commit comments

Comments
 (0)