最近在 EndeavourOS 上挂载一个 1TB 的 NTFS 移动硬盘时遇到问题。这个盘本身没有明显硬件故障,放到 Ubuntu 20.04 上可以挂载,但在当前系统上通过文件管理器点击挂载会失败。

当前系统环境:

  • 发行版:EndeavourOS / Arch Linux
  • 内核:Linux 7.1.2-arch3-1
  • udisks2:2.11.1-2
  • util-linux:2.42.2-1
  • ntfs-3g:2026.2.25-1
  • 目标分区:/dev/sdb1,NTFS,UUID 为 0EA516700EA51670

这篇记录一下排查过程,以及如何让系统优先使用 Linux 7.1 新合入的 ntfs 内核驱动。

问题现象

文件管理器弹窗报错:

TEXT
Unable to access "1.0 TB Volume"

Error mounting /dev/sda1 at /run/media/jiang/0EA516700EA51670:
wrong fs type, bad option, bad superblock on /dev/sda1,
missing codepage or helper program, or other error

这个提示比较泛,只能说明 mount 系统调用失败。真正原因要看内核日志:

BASH
journalctl -k -b --no-pager | grep -Ei 'ntfs|sda|sdb'

关键日志如下:

TEXT
ntfs3(sda1): It is recommended to use chkdsk.
ntfs3(sda1): volume is dirty and "force" flag is not set!

重新插拔后设备名可能从 /dev/sda1 变成 /dev/sdb1,但错误本质一样:

TEXT
ntfs3(sdb1): It is recommended to use chkdsk.
ntfs3(sdb1): volume is dirty and "force" flag is not set!

也就是说,文件管理器默认走的是 ntfs3 内核驱动,而这个 NTFS 卷被标记为 dirty。ntfs3 默认拒绝挂载 dirty volume。

为什么 Ubuntu 20.04 能挂

Ubuntu 20.04 通常走的是 ntfs-3g,它是 FUSE 用户态驱动。Arch/EndeavourOS 的新系统里,文件管理器通过 udisks2 挂载 NTFS 时可能优先尝试 ntfs3

所以“Ubuntu 能挂”不等于“当前内核的 ntfs3 也会挂”。这是两个不同驱动的行为差异。

Linux 7.1 里的新 ntfs 驱动

这里还有一个容易混淆的点:Linux 7.1 里新增/重写的驱动叫 ntfs,不是 ntfs3

当前系统里可以看到两个内核模块都存在:

BASH
modinfo ntfs | sed -n '1,20p'
modinfo ntfs3 | sed -n '1,20p'

ntfs 模块信息:

TEXT
filename:       /lib/modules/7.1.2-arch3-1/kernel/fs/ntfs/ntfs.ko.zst
description:    NTFS read-write filesystem driver
author:         Namjae Jeon <linkinjeon@kernel.org>
alias:          fs-ntfs

内核配置也能看到:

BASH
zgrep -E 'CONFIG_NTFS|CONFIG_NTFS3' /proc/config.gz

输出类似:

TEXT
CONFIG_NTFS_FS=m
CONFIG_NTFS_DEBUG=y
CONFIG_NTFS_FS_POSIX_ACL=y
CONFIG_NTFS3_FS=m
CONFIG_NTFS3_LZX_XPRESS=y
CONFIG_NTFS3_FS_POSIX_ACL=y

这说明系统同时有:

  • ntfs:Linux 7.1 新的内核 NTFS 驱动
  • ntfs3:Linux 5.15 起合入的 Paragon NTFS3 驱动
  • ntfs-3g:用户态 FUSE 驱动

官方文档:

手动使用新的 ntfs 内核驱动

如果想确认自己确实用的是 Linux 7.1 新 ntfs 驱动,推荐先只读挂载:

BASH
sudo mkdir -p /mnt/ntfs-test
sudo modprobe ntfs
sudo mount -i -t ntfs -o ro,uid=$(id -u),gid=$(id -g),umask=022 \
  /dev/disk/by-uuid/0EA516700EA51670 /mnt/ntfs-test

这里最关键的是 -i

TEXT
-i, --internal-only
    don't call the mount.<type> helpers

因为当前系统里:

BASH
ls -l /usr/bin/mount.ntfs /usr/bin/mount.ntfs-3g

输出是:

TEXT
/usr/bin/mount.ntfs -> /usr/bin/ntfs-3g
/usr/bin/mount.ntfs-3g -> /usr/bin/ntfs-3g

如果不加 -imount -t ntfs 可能会调用 mount.ntfs helper,最后实际走到 ntfs-3g,而不是新内核驱动。

挂载后验证:

BASH
findmnt -no SOURCE,FSTYPE,OPTIONS /mnt/ntfs-test

如果输出里的 FSTYPEntfs,才表示正在使用新内核驱动:

TEXT
/dev/sdb1 ntfs ro,relatime,uid=1000,gid=1001,umask=022,...

如果看到的是:

TEXT
fuseblk

那就是 ntfs-3g

如果看到:

TEXT
ntfs3

那就是 Paragon 的 ntfs3,不是 Linux 7.1 新 ntfs

卸载:

BASH
sudo umount /mnt/ntfs-test

修改 udisks2 的 NTFS 驱动顺序

文件管理器通常不是直接调用 mount,而是通过 udisks2 挂载。udisks2 的 NTFS 驱动顺序可以通过 /etc/udisks2/mount_options.conf 调整。

如果没有这个文件,可以从示例复制:

BASH
sudo cp /etc/udisks2/mount_options.conf.example /etc/udisks2/mount_options.conf

然后编辑:

BASH
sudoedit /etc/udisks2/mount_options.conf

最小配置如下:

INI
[defaults]
ntfs_drivers=ntfs,ntfs3

这表示让 udisks2 优先尝试 ntfs,再尝试 ntfs3

一个容易犯的配置错误

一开始我只取消注释了这一行:

INI
ntfs_drivers=ntfs,ntfs3

但前面的 group 仍然是注释状态:

INI
# [defaults]
ntfs_drivers=ntfs,ntfs3

这样 udisks2 会直接忽略整个配置文件,并在日志里报:

TEXT
Error reading global mount options config file /etc/udisks2/mount_options.conf:
Key file does not start with a group

所以必须确保 [defaults] 没有被注释:

INI
[defaults]
ntfs_drivers=ntfs,ntfs3

修改后重启 udisks2:

BASH
sudo systemctl restart udisks2

如果桌面环境的 volume monitor 还缓存旧状态,可以重启用户侧服务,或者直接退出重新登录:

BASH
systemctl --user restart gvfs-udisks2-volume-monitor.service 2>/dev/null || true

再次点击文件管理器挂载后,用下面命令确认实际使用的驱动:

BASH
findmnt -t ntfs,ntfs3,fuseblk

注意 udisks2 与 mount.ntfs helper

ntfs_drivers=ntfs,ntfs3 能改变 udisks2 的尝试顺序,但不代表最终一定会落到 Linux 7.1 新 ntfs 内核驱动。

在当前系统上,/usr/bin/mount.ntfsntfs-3g 的软链接:

TEXT
/usr/bin/mount.ntfs -> /usr/bin/ntfs-3g

实际测试:

BASH
udisksctl mount --filesystem-type=ntfs --options=ro \
  --block-device=/dev/disk/by-uuid/0EA516700EA51670

最后可能会挂成:

TEXT
FSTYPE=fuseblk

这说明 udisks2 通过 mount.ntfs helper 走到了 ntfs-3g

所以结论是:

  • 想让文件管理器不要优先撞上 ntfs3 的 dirty 拒绝,可以配置 ntfs_drivers=ntfs,ntfs3
  • 想严格使用 Linux 7.1 新内核 ntfs 驱动,最可靠的方法是手动执行 mount -i -t ntfs ...,跳过 helper。
  • 挂载后一定用 findmnt 看实际 FSTYPE,不要只看命令参数。

dirty volume 的正确处理

这次根因仍然是 NTFS dirty flag:

TEXT
volume is dirty and "force" flag is not set

最稳妥的修复方式是在 Windows 里运行:

CMD
chkdsk X: /f

其中 X: 换成 Windows 下对应盘符。

如果这个盘经常在 Windows 和 Linux 之间切换,也建议关闭 Windows 休眠/快速启动:

CMD
powercfg /h off

Linux 下的 ntfsfix 可以做一些有限处理,但它不是完整的 chkdsk 替代品。尤其是 dirty volume 上有重要数据时,不建议直接强行读写挂载。

如果只是临时拷贝数据,优先使用只读挂载:

BASH
sudo mount -i -t ntfs -o ro,uid=$(id -u),gid=$(id -g),umask=022 \
  /dev/disk/by-uuid/0EA516700EA51670 /mnt/ntfs-test

排查命令汇总

查看分区和文件系统:

BASH
lsblk -o NAME,PATH,FSTYPE,LABEL,UUID,SIZE,TYPE,MOUNTPOINTS,MODEL

查看当前 NTFS 挂载:

BASH
findmnt -t ntfs,ntfs3,fuseblk

查看内核日志:

BASH
journalctl -k -b --no-pager | grep -Ei 'ntfs|sda|sdb|mount'

查看 udisks2 日志:

BASH
journalctl -b -u udisks2 --no-pager

查看 udisks2 识别到的设备信息:

BASH
udisksctl info -b /dev/disk/by-uuid/0EA516700EA51670

查看系统是否有新 ntfs 模块:

BASH
modinfo ntfs
cat /proc/filesystems | grep -E 'ntfs|fuseblk'

查看 mount.ntfs 是否被 ntfs-3g 接管:

BASH
ls -l /usr/bin/mount.ntfs /usr/bin/mount.ntfs-3g

总结

这次问题不是内核没升级,也不是 Linux 没有 NTFS 支持,而是几个层次叠在一起:

  • 盘被 NTFS 标记为 dirty。
  • 文件管理器通过 udisks2 默认走 ntfs3
  • ntfs3 默认拒绝挂载 dirty volume。
  • Linux 7.1 的新驱动叫 ntfs,需要和 ntfs3 区分。
  • /etc/udisks2/mount_options.conf 必须有 [defaults] group,否则配置会被忽略。
  • mount -t ntfs 不一定等于新内核 ntfs,因为 mount.ntfs 可能指向 ntfs-3g
  • 真正确认驱动只能看 findmntFSTYPE

最终配置文件中保留:

INI
[defaults]
ntfs_drivers=ntfs,ntfs3

需要明确使用 Linux 7.1 新 ntfs 内核驱动时,使用:

BASH
sudo mount -i -t ntfs -o ro,uid=$(id -u),gid=$(id -g),umask=022 \
  /dev/disk/by-uuid/0EA516700EA51670 /mnt/ntfs-test

重要数据盘仍然建议先在 Windows 上跑 chkdsk /f,不要把 force 或清 dirty flag 当成常规修复手段。