# 出问题了

日常在 Manjaro 和 Windows 双系统穿梭的我,某天进 Windows 前,突然发现 D 盘“未格式化”。这次 Windows 开机的时候还显示 □□□□□□□□ (D: ): 100%。大概率是 Windows 磁盘检查的锅。

在 Windows 下使用傲梅分区助手看了一下,发现我的 D 盘变成 ext4 了。嗯?他重启前不还是 NTFS 的吗?因此,我猜测是 Windows(或者 Linux)把这个分区的类型搞错了,实际数据还是按 NTFS 数据存的。

考虑到 Windows 下一碰 ext4 就提示你“是否格式化”,我还是进 Manjaro 搞吧。

# 进 Linux 看看

Manjaro 开机后,显示 /dev/nvme0n1p6(也就是上面所说的 D 盘)无法挂载,原因是:

Structure needs cleaning

稍微搜了一下(挂载磁盘报错“Structure needs cleaning”_Wdddddddddd_51CTO博客 (opens new window)ubuntu - Cannot remove file: "Structure needs cleaning" - Unix & Linux Stack Exchange (opens new window)),看看自己的是什么情况。

先看看现在的分区是什么样的吧。

$ sudo fdisk -l
[sudo] liu 的密码:
Disk /dev/nvme1n1:476.94 GiB,512110190592 字节,1000215216 个扇区
磁盘型号:INTEL SSDPEKKW512G8                     
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:gpt
磁盘标识符:7573E7D7-A331-4409-A786-43099F7F0453

设备                起点       末尾      扇区   大小 类型
/dev/nvme1n1p1      2048    1126398   1124351   549M EFI 系统
/dev/nvme1n1p2   1126400  998855191 997728792 475.8G Microsoft 基本数据
/dev/nvme1n1p3 998857440 1000211119   1353680   661M Windows 恢复环境


Disk /dev/nvme0n1:931.51 GiB,1000204886016 字节,1953525168 个扇区
磁盘型号:Samsung SSD 980 PRO 1TB                 
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:gpt
磁盘标识符:EF342227-7AEA-4279-9C6D-89D1023BA48A

设备                 起点       末尾       扇区  大小 类型
/dev/nvme0n1p1         34      32767      32734   16M BIOS 启动
/dev/nvme0n1p2      32768    1081343    1048576  512M Linux 文件系统
/dev/nvme0n1p3    1081344  420511743  419430400  200G Linux 文件系统
/dev/nvme0n1p4  420511744  839942143  419430400  200G Linux 文件系统
/dev/nvme0n1p5  839942144  881885183   41943040   20G Linux swap
/dev/nvme0n1p6  881885184 1953517567 1071632384  511G Microsoft 基本数据
/dev/nvme0n1p7 1953520064 1953525134       5071  2.5M Microsoft 保留

fdisk -l 看不出来具体类型,换 parted -l

sudo parted -l
型号:Samsung SSD 980 PRO 1TB (nvme)
磁盘 /dev/nvme0n1:1000GB
扇区大小 (逻辑/物理):512B/512B
分区表:gpt
磁盘标志:

编号  起始点  结束点  大小    文件系统        名称                          标志
 1    17.4kB  16.8MB  16.8MB                                                bios_grub
 2    16.8MB  554MB   537MB   ext4
 3    554MB   215GB   215GB   ext4
 4    215GB   430GB   215GB   ext4
 5    430GB   452GB   21.5GB  linux-swap(v1)                                交换
 6    452GB   1000GB  549GB   ext4            Basic data partition          msftdata
 7    1000GB  1000GB  2596kB                  Microsoft reserved partition  msftres


型号:INTEL SSDPEKKW512G8 (nvme)
磁盘 /dev/nvme1n1:512GB
扇区大小 (逻辑/物理):512B/512B
分区表:gpt
磁盘标志:

编号  起始点  结束点  大小   文件系统  名称  标志
 1    1049kB  577MB   576MB  fat32           启动, EFI 启动
 2    577MB   511GB   511GB  ntfs            msftdata
 3    511GB   512GB   693MB  ntfs            诊断

可以看到,/dev/nvme0n1p6 虽然是 msftdata,但文件系统居然是 ext4

# 尝试 fsck 修复

上面两个链接都提到使用 fsck 修复,于是我们跑一下。

到这里我还不确定原本的分区确定肯定以及一定是 NTFS,于是我跑了一下修复 ext4 的命令行:

$ sudo fsck.ext4 /dev/nvme0n1p6
e2fsck 1.46.4 (18-Aug-2021)
ext2fs_check_desc: 组描述符损坏:块位图中有坏块
fsck.ext4:组描述符似乎是错误的... 尝试备份块
fsck.ext4:尝试备份块时 超级块中的幻数有错fsck.ext4:回到原先的超级块
超级块含有一个无效的日志(inode 8)。
清除<y>? 是
*** journal has been deleted ***

注意:如果有数个inode、块位图或inode表
需要重定位,你可以用“-b 32768”选项运行
e2fsck。如果问题出在组描述符的主块,
那么可以尝试它们的备份块。

组 0 的块位图并不在 组 中。(块 7449066062970102630)
重定位<y>? 是
组 0 的inode位图 并不在 组 中。(块 2387591211039621)
重定位<y>? 是
组 0 的inode表并不在 组 中。(块 3524000321174401)
警告:这可能导致严重的数据丢失。
重定位<y>? 是
一个或多个块组描述符的校验值无效。  处理<y>? 是
组描述符 0 的校验值为0x0607,应当为 0x6e89。  已处理.
组 1 的块位图并不在 组 中。(块 14493541264792102986)
重定位<y>? 是
组 1 的inode位图 并不在 组 中。(块 14218948929126649)
重定位<y>? 是
组 1 的inode表并不在 组 中。(块 9223576984314121984)
警告:这可能导致严重的数据丢失。
重定位<y>? 是
组描述符 1 的校验值为0xf5e8,应当为 0xc820。  已处理.
组 2 的块位图并不在 组 中。(块 5783559511694953099)
重定位<y>? 是
组 2 的inode位图 并不在 组 中。(块 53874154171787517)
重定位(“a” 表示全部回答“yes”) <y>? 是
组 2 的inode表并不在 组 中。(块 7349874730908146278)
警告:这可能导致严重的数据丢失。
重定位(“a” 表示全部回答“yes”) <y>? 是
组描述符 2 的校验值为0x6607,应当为 0xbddf。  已处理.

.....


组描述符 141 的校验值为0x01af,应当为 0x927a。  已处理.
组 142 的块位图并不在 组 中。(块 130887852769739200)
重定位<y>? 否
组 142 的inode位图 并不在 组 中。(块 131450811313226178)
重定位<y>? 已取消!
组 142 的inode表并不在 组 中。(块 132013769856713156)
警告:这可能导致严重的数据丢失。
重定位<y>? 已取消!
组描述符 142 的校验值为0x01cf,应当为 0x288c。  已处理.

/dev/nvme0n1p6:***** 文件系统已修改 *****

/dev/nvme0n1p6:********** 警告:文件系统上仍有错误 **********

改到一半,发现不对劲,赶紧 Ctrl + C

所以,它真的是 NTFS。那怎么修呢?并不存在 fsck.ntfs 这种东西,但是稍微一 Google 就能搜到 ntfsfix 这个好东西。

$ ntfsfix
ERROR: You must specify a device.
ntfsfix v2021.8.22 (libntfs-3g)

Usage: ntfsfix [options] device
    Attempt to fix an NTFS partition.

    -b, --clear-bad-sectors Clear the bad sector list
    -d, --clear-dirty       Clear the volume dirty flag
    -h, --help              Display this help
    -n, --no-action         Do not write anything
    -V, --version           Display version information

For example: ntfsfix /dev/hda6

Developers' email address: ntfs-3g-devel@lists.sf.net
News, support and information:  http://tuxera.com

$ sudo ntfsfix /dev/nvme0n1p6
Mounting volume... NTFS signature is missing.
FAILED
Attempting to correct errors... NTFS signature is missing.
FAILED
Failed to startup volume: Invalid argument
NTFS signature is missing.
Trying the alternate boot sector
The alternate bootsector is usable
Rewriting the bootsector
The boot sector has been rewritten

Processing $MFT and $MFTMirr...
Reading $MFT... OK
Reading $MFTMirr... OK
Comparing $MFTMirr to $MFT... OK
Processing of $MFT and $MFTMirr completed successfully.
Setting required flags on partition... OK
Going to empty the journal ($LogFile)... OK
Checking the alternate boot sector... OK
NTFS volume version is 3.1.
NTFS partition /dev/nvme0n1p6 was processed successfully.

看起来挺顺利的。parted -l 检查一下:

$ sudo parted -l
型号:Samsung SSD 980 PRO 1TB (nvme)
磁盘 /dev/nvme0n1:1000GB
扇区大小 (逻辑/物理):512B/512B
分区表:gpt
磁盘标志:

编号  起始点  结束点  大小    文件系统        名称                          标志
 1    17.4kB  16.8MB  16.8MB                                                bios_grub
 2    16.8MB  554MB   537MB   ext4
 3    554MB   215GB   215GB   ext4
 4    215GB   430GB   215GB   ext4
 5    430GB   452GB   21.5GB  linux-swap(v1)                                交换
 6    452GB   1000GB  549GB   ntfs            Basic data partition          msftdata
 7    1000GB  1000GB  2596kB                  Microsoft reserved partition  msftres

对的。

挂载一下试试:

$ sudo mount /dev/nvme0n1p6 /run/media/liu/Documents
mount: /run/media/liu/Documents: /dev/nvme0n1p6 上探测到了更多文件系统;请使用 -t <类型> 或 wipefs(8).

唔。搜了一下 探测到了更多文件系统,原文是 more filesystems detected。没有搜到太多有用的东西。

# “探测到了更多文件系统”

既然这样,先试试 mount -t 吧。

$ sudo mount /dev/nvme0n1p6 /run/media/liu/Documents -t ntfs
$ sudo ls /run/media/liu/Documents

成功看到它~~生前(bushi)~~之前的文件。

试一下 wipefs 呢?

$ wipefs
wipefs: 未指定设备
请尝试执行“wipefs --help”了解更多信息。

$ wipefs --help

用法:
 wipefs [选项] <设备>

从设备擦除签名。

选项:
 -a, --all           wipe all magic strings (BE CAREFUL!)
 -b, --backup        create a signature backup in $HOME
 -f, --force         force erasure
 -i, --noheadings    don't print headings
 -J, --json          使用 JSON 输出格式
 -n, --no-act        do everything except the actual write() call
 -o, --offset <num>  offset to erase, in bytes
 -O, --output <list> COLUMNS to display (see below)
 -p, --parsable      print out in parsable instead of printable format
 -q, --quiet         禁止输出信息
 -t, --types <list>  limit the set of filesystem, RAIDs or partition tables
     --lock[=<mode>] use exclusive device lock (yes, no or nonblock)
 -h, --help          显示此帮助
 -V, --version       显示版本

Arguments:
 <num> arguments may be followed by the suffixes for
   GiB, TiB, PiB, EiB, ZiB, and YiB (the "iB" is optional)

可用的输出列:
     UUID  分区/文件系统 UUID
    LABEL  文件系统标签
   LENGTH  magic string length
     TYPE  超级块类型
   OFFSET  magic string offset
    USAGE  类型描述
   DEVICE  块设备名称

更多信息请参阅 wipefs(8)。

嗯,看起来直接调用 wipefs 不会字如其名地 wipe,而是展示信息。那就跑一下吧。

$ sudo wipefs /dev/nvme0n1p6
DEVICE    OFFSET TYPE UUID                                 LABEL
nvme0n1p6 0x438  ext4 f6be4202-5847-4722-b5bd-654166abdacd 
nvme0n1p6 0x3    ntfs 4ABAA764BAA74AF1                     Documents

好!一切都能解释通了。这个分区同时拥有 ext4 和 NTFS 两种签名。所以,可以删掉一种吗?

$ sudo umount /dev/nvme0n1p6
$ sudo wipefs /dev/nvme0n1p6 -b -t ntfs -a
/dev/nvme0n1p6:8 个字节已擦除,位置偏移为 0x00000003 (ntfs):4e 54 46 53 20 20 20 20

不对!上面的命令是删掉 NTFS 签名,并非只保留 NTFS 签名!但我发现的时候已经晚了。

$ sudo wipefs /dev/nvme0n1p6
DEVICE    OFFSET TYPE UUID                                 LABEL
nvme0n1p6 0x438  ext4 f6be4202-5847-4722-b5bd-654166abdacd 

在想怎么救之前,先把 ext4 签名也删了吧。

$ sudo wipefs /dev/nvme0n1p6 -b -t ext4 -a
/dev/nvme0n1p6:2 个字节已擦除,位置偏移为 0x00000438 (ext4):53 ef

$ sudo wipefs /dev/nvme0n1p6
# 这下真的啥都没了

突然想到 ntfsfix,跑一下试试:

$ sudo ntfsfix /dev/nvme0n1p6
Mounting volume... NTFS signature is missing.
FAILED
Attempting to correct errors... NTFS signature is missing.
FAILED
Failed to startup volume: Invalid argument
NTFS signature is missing.
Trying the alternate boot sector
The alternate bootsector is usable
Rewriting the bootsector
The boot sector has been rewritten

Processing $MFT and $MFTMirr...
Reading $MFT... OK
Reading $MFTMirr... OK
Comparing $MFTMirr to $MFT... OK
Processing of $MFT and $MFTMirr completed successfully.
Setting required flags on partition... OK
Going to empty the journal ($LogFile)... OK
Checking the alternate boot sector... OK
NTFS volume version is 3.1.
NTFS partition /dev/nvme0n1p6 was processed successfully.

$ sudo wipefs /dev/nvme0n1p6
DEVICE    OFFSET TYPE UUID             LABEL
nvme0n1p6 0x3    ntfs 4ABAA764BAA74AF1 Documents

好耶!此贴完结。