From nobody Thu Sep 03 02:16:49 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hb3Bb58K3z6qMZd for ; Thu, 03 Sep 2026 02:16:55 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hb3Bb2clNz3TZ7 for ; Thu, 03 Sep 2026 02:16:55 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788401815; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=29NdS/ahyUPw6w1PuXvnqg5ns6cW/ZTwFyO9tjcY5RY=; b=jk82JBzIciRpWYZfjjSOjeWviIy3TCK1ahP4F82vythou8sn4LUCd0lLl+eul+JdPaW6BF 3RqsVy9g89etiSf0fRKtyBRz2rgT1kAlpBRZ0DvTiVP8Z07gPvGbRSGv53SMWLjDOseeOJ tKfsW4olOch4jNuCXeC4BIH69DMWaO7JD4Vt4xIjEHjSV3cgvW1ZON/Qv6DudyB32T6+rm RKLSJ3sIaApTC5z9eZ5kdE23DjxEGCA1306jVNz1Htrd7oLje8oj0eDeG6CSDgfHQ3YpER Bn4QQOzsc1IymWsrbYvM1Nkhre0qHUSceZVaFpU7NpTaFw8R8TfeQSGKcILGsA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788401815; a=rsa-sha256; cv=none; b=ee5aK8SdonXyW0jqUGtRZEph00GPa950capjoh4CeOF1Uwc1phOPi9oYLyBLBY8JknBQXs FV2g4g6A2bKidITPlqpCyvhHoO1WMaN68O9dAYPNdOQc/T+2IehSM4UzN0e6wHzrGonIZk edZO0lhZWrWgowuxwCwF8jwqtY7eAzcSIfvqYlt4znFnxW7fD/dG6rn0IoPG/+c7NdKLyX MPkwTfs6LaMgUepTKphLSHsEaq3/AQImw6+0T13WRpVjJmV+MmhgLja7Dn/lxsKZXBJOIx DAF1ydex7HltBT6ugC7XjNiVoLn1xIyxx/WVPO3GvIPs15Ba4opEaobntGS4XA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788401815; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=29NdS/ahyUPw6w1PuXvnqg5ns6cW/ZTwFyO9tjcY5RY=; b=jyHMMGDSNqoCGy8uVp+9e8jZTDTV9KQrjttG20ZDR5vhvg07Vz4ir7Sc8+/qmf+2mWsJBh stban35JcCY97v8hAqG/Nh8Rm3HAm4NF2kezuqqvhC0vb2cIcJepYcThNErswNg8pKXUoy fMdDqFzPuOYjTgAUQlz3OdVVOCddV+MYcPdDlNogH+04XG10tf1pgAs2snIX08bnN7Cq9t /bQoWQymbNoLWJjQj12cMBQQ93enPzodZWAsXyqbGmDnvqMfM3UrLGipPJMW4kfGVLJt7r 19rMx8erV7o664WNztuNhVNTtq5VxnIc2yOOYmbgTAPyI8qgivIYYyzYxboefA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hb3Bb1b8Mz189m for ; Thu, 03 Sep 2026 02:16:55 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 259a9 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 03 Sep 2026 02:16:49 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Jie Li From: Xin LI Subject: git: 6cf0d6c3b577 - main - fsck_msdosfs: fix status accounting for lost cluster chains List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: delphij X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 6cf0d6c3b5777e053074200ff99dc4b750e62b96 Auto-Submitted: auto-generated Date: Thu, 03 Sep 2026 02:16:49 +0000 Message-Id: <6a98d891.259a9.4ddf66ce@gitrepo.freebsd.org> The branch main has been updated by delphij: URL: https://cgit.FreeBSD.org/src/commit/?id=6cf0d6c3b5777e053074200ff99dc4b750e62b96 commit 6cf0d6c3b5777e053074200ff99dc4b750e62b96 Author: Jie Li AuthorDate: 2026-09-02 06:15:05 +0000 Commit: Xin LI CommitDate: 2026-09-03 02:16:10 +0000 fsck_msdosfs: fix status accounting for lost cluster chains checklost() scans for lost cluster chains and attempts to repair each one, first by reconnecting it to LOST.DIR, and falling back to clearing it if reconnection fails. However, checklost() incorrectly updates the modification status flags (mod), which checkfilesys() relies on to determine whether to write back changes and what exit status to return. The current code have three issues: 1. A reconnect() failure immediately sets FSERROR in mod via "mod |= ret = reconnect(...)". If reconnect() failed (e.g., because LOST.DIR is missing, or full) but the fallback clear operation succeeds, clearchain() frees the chain and sets FSFATMOD. However, the leftover FSERROR remains in mod: checkfilesys() skips marking the file system clean and exits with status 8, even though the file system was fully repaired and a subsequent run finds nothing left to do. This can happen with "fsck_msdosfs -y" on a volume without LOST.DIR. 2. The same assignment overwrites checkchain()'s return value before it can be recorded in mod. When checkchain() truncates a chain (e.g., one whose tail points to a free cluster), its FSFATMOD status is lost, causing checkfilesys() to skip updating the FAT and discard the truncation. With LOST.DIR present so that reconnect() succeeds, "fsck_msdosfs -y" reports "Truncate? yes" and "FILE SYSTEM WAS MODIFIED", exits 0, but leaves the identical damage on disk to be found again on every subsequent run. Similarly, an FSFATAL return value from checkchain() is dropped, defeating the "if (mod & FSFATAL) break" guard that follows. 3. When checkchain() returns FSERROR and clearing the chain is declined, no error status is recorded in mod, causing fsck_msdosfs to report a clean exit despite leaving un-repaired damage. Fix these issues by: - Merge checkchain()'s status into mod before calling reconnect(), and skip reconnect() if checkchain() returned a fatal error. - Defer recording FSERROR from a failed reconnect() until after the Clear fallback attempt, setting FSERROR only if the chain remains unhandled. MFC after: 1 week Pull Request: https://github.com/freebsd/freebsd-src/pull/2251 --- sbin/fsck_msdosfs/fat.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/sbin/fsck_msdosfs/fat.c b/sbin/fsck_msdosfs/fat.c index 5ead0b1bf783..d71ac2b503f5 100644 --- a/sbin/fsck_msdosfs/fat.c +++ b/sbin/fsck_msdosfs/fat.c @@ -1284,18 +1284,41 @@ checklost(struct fat_descriptor *fat) } if (fat_is_cl_head(fat, head)) { ret = checkchain(fat, head, &chainlength); - if (ret != FSERROR && chainlength > 0) { - pwarn("Lost cluster chain at cluster %u\n" - "%zd Cluster(s) lost\n", - head, chainlength); - mod |= ret = reconnect(fat, head, - chainlength); + /* + * Record whether checkchain() has repaired the + * chain (FSFATMOD) or died trying (FSFATAL) before + * reconnect() overwrites ret, otherwise the repair + * is never written back. + */ + if (ret != FSERROR) { + mod |= ret; + if (!(mod & FSFATAL) && chainlength > 0) { + pwarn( + "Lost cluster chain at cluster %u\n" + "%zd Cluster(s) lost\n", + head, chainlength); + ret = reconnect(fat, head, chainlength); + if (ret != FSERROR) + mod |= ret; + } } if (mod & FSFATAL) break; - if (ret == FSERROR && ask(0, "Clear")) { - clearchain(fat, head); - mod |= FSFATMOD; + /* + * If reconnect() failed (or checkchain() truncation + * was declined), defer folding FSERROR into mod until + * the Clear fallback is known: if the lost chain is + * cleared, the error has been resolved and must not + * report an exit code 8; otherwise record FSERROR as + * an unrecovered error. + */ + if (ret == FSERROR) { + if (ask(0, "Clear")) { + clearchain(fat, head); + mod |= FSFATMOD; + } else { + mod |= FSERROR; + } } chains--; }