git: ae32d61a2e3e - stable/15 - fsck_msdosfs: fix FAT header correction not persisting in cache mode

From: Xin LI <delphij_at_FreeBSD.org>
Date: Tue, 12 May 2026 05:16:14 UTC
The branch stable/15 has been updated by delphij:

URL: https://cgit.FreeBSD.org/src/commit/?id=ae32d61a2e3e47bed54d861893d8e2da90fb7c76

commit ae32d61a2e3e47bed54d861893d8e2da90fb7c76
Author:     Lianwei Wang <lianwei.wang@gm.com>
AuthorDate: 2026-05-09 04:56:12 +0000
Commit:     Xin LI <delphij@FreeBSD.org>
CommitDate: 2026-05-12 05:15:41 +0000

    fsck_msdosfs: fix FAT header correction not persisting in cache mode
    
    When fsck_msdosfs runs with FAT32 cache mode (used for large
    filesystems that cannot be mmap'd), a detected FAT header correction
    was written into the in-memory buffer but the corresponding cache
    entry (fat32_cache_allentries[0]) was never marked dirty.  As a
    result, fat_flush_fat32_cache_entry() skipped it, the corrected
    bytes were never written to disk, and copyfat() propagated the
    uncorrected on-disk data to all backup FAT copies.  Every subsequent
    fsck run would repeat the same "FAT starts with odd byte sequence /
    FIXED" cycle indefinitely.
    
    Fix by marking fat32_cache_allentries[0].dirty = true after applying
    the in-memory correction, ensuring the chunk is flushed before
    copyfat() runs.
    
    Obtained from:  https://android-review.googlesource.com/c/platform/external/fsck_msdos/+/4047981
    
    (cherry picked from commit 10e342c1ec78af5a0b97739c806b16a632118fa5)
---
 sbin/fsck_msdosfs/fat.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/sbin/fsck_msdosfs/fat.c b/sbin/fsck_msdosfs/fat.c
index 567bfcd428cb..5ead0b1bf783 100644
--- a/sbin/fsck_msdosfs/fat.c
+++ b/sbin/fsck_msdosfs/fat.c
@@ -927,6 +927,17 @@ readfat(int fs, struct bootblock *boot, struct fat_descriptor **fp)
 				default:
 					break;
 				}
+				/*
+				 * In cache mode the header lives in
+				 * fat32_cache_allentries[0].  Mark it
+				 * dirty so it is flushed to disk (either
+				 * on eviction or in writefat()) before
+				 * copyfat() copies the primary FAT to
+				 * backup copies.
+				 */
+				if (fat->use_cache)
+					fat->fat32_cache_allentries[0].dirty =
+					    true;
 			}
 		}
 	}