摘要: E2fsck 发现-n
选项没有错误,但使用-p
(preen)。它更正了错误,但没有给出任何错误消息。该错误仅通过退出代码反映。如何解释这个?
我正在使用带有 Ext2 文件系统的 USB 硬盘驱动器来存储多台机器的备份。最近,我在该驱动器上获得了巨大的数据吞吐量,因此我决定进行额外的文件系统检查。总的来说,我e2fsck
用不同的选项进行了四次跑步。以下是我(以 root 身份)使用的命令及其输出,其中还包含e2fsck
. 不幸的是,有些短语被本地化为德语,但(可能)重要的是英语:
第一次运行,只读:
# e2fsck -nv /dev/sdb1; echo $?
e2fsck 1.41.1 (01-Sep-2008)
WD-Elements: sauber, 709312/61046784 Dateien, 96258851/244182016 Blöcke
0
第二次运行,只读强制:
# e2fsck -nfv /dev/sdb1; echo $?
e2fsck 1.41.1 (01-Sep-2008)
Durchgang 1: Prüfe Inodes, Blocks, und Größen
Durchgang 2: Prüfe Verzeichnis Struktur
Durchgang 3: Prüfe Verzeichnis Verknüpfungen
Durchgang 4: Überprüfe die Referenzzähler
Durchgang 5: Überprüfe Gruppe Zusammenfassung
709312 inodes used (1.16%)
95492 non-contiguous inodes (13.5%)
# von Inodes mit ind/dind/tind Blöcken: 109958/2429/7
96258851 blocks used (39.42%)
0 bad blocks
8 large files
564029 regular files
121351 directories
0 character device files
0 block device files
11 fifos
506224 links
23073 symbolic links (19397 fast symbolic links)
839 sockets
--------
1215527 files
0
第三次运行,整理:
# e2fsck -pv /dev/sdb1; echo $?
WD-Elements: sauber, 709312/61046784 Dateien, 96258851/244182016 Blöcke
0
第 4 次运行,强制整理:
# e2fsck -pfv /dev/sdb1; echo $?
709312 inodes used (1.16%)
95492 non-contiguous inodes (13.5%)
# von Inodes mit ind/dind/tind Blöcken: 109958/2429/7
96258853 blocks used (39.42%)
0 bad blocks
8 large files
564029 regular files
121351 directories
0 character device files
0 block device files
11 fifos
506224 links
23073 symbolic links (19397 fast symbolic links)
839 sockets
--------
1215527 files
1
命令一个接一个地直接发出,中间没有触及任何其他东西。
请注意差异:
在前两次运行中,文件系统以只读方式打开(
-n
选项),而后两次正在整理运行(-p
选项)。第一次和第三次运行不是强制的,第二次和最后一次运行是(
-f
)。所有运行都报告了一致的文件系统数据,但有一个例外:最后一次运行 (
-pfv
) 报告了不同数量的“使用的块”。除了最后一次运行以外的所有运行都以状态 0 退出,最后一次 (
-pfv
) 以状态 1 退出。
显然,最后一次强制整理运行 ( -pfv
) 发现(并纠正了)其他运行无法找到的文件系统错误。不幸的是,它没有在其输出中给出任何关于该错误的提示。
现在我的问题:
在那里发现并纠正了什么错误?是否像使用过的块数不正确一样简单?
什么可能导致该错误?文件系统总是干净地卸载。
文件系统错误最终由
e2fsck
. 但是我可以信任其中存储的数据吗?难道不是首先导致该文件系统错误的任何东西也损坏了磁盘上的数据吗?这将使磁盘上的所有数据一文不值。或者这是偏执狂?为什么?
最后一个问题区分文件系统和数据。在这方面,Mikel对“ Do journaling filesystems保证在电源故障后不会损坏? ”的回答具有高度相关性。不幸的是,它专注于日志文件系统,因此不适用于 Ext2。
Gilles对“如何测试 fsck 完成的文件系统更正”的回答也很好读:据此,fsck
仅保证文件系统的一致状态,不一定是最新状态。
更新 1
Luciano Andress Martini在他的评论中指出,观察到且明显令人费解的行为e2fsck
可能是由执行机器中的 RAM 错误引起的。虽然在可比较的情况下是一个高度相关的方面,但它似乎不适用于这里:我用“memtest86+”检查了 RAM 过夜,它完成了 16 次通过而没有错误。此外,我使用另一台机器(不同的硬件、内核和版本)在被测驱动器上执行e2fsck -nfv
、e2fsck -pfv
和运行。这些没有发现任何文件系统错误,并确认了上次报告的文件系统数据e2fsck -fv
e2fsck
e2fsck
上面显示的命令,特别是使用的块数。还确认了非强制检查报告的块总数(244182016)。
更新 2
telcoM 的回答表明,观察到的行为e2fsck
可以用e2fsck
处理非常旧的文件系统时文件系统功能设置的更改来解释。不幸的是,这种非常一致的解释在这里并不适用:文件系统实际上是用更新版本的mke2fs
(1.42.8) 创建的,它启用了特性ext_attr
, resize_inode
, dir_index
, filetype
, 。上述运行并未改变这一点。sparse_super
large_file
e2fsck
更新 3
同时,USB 驱动器成功通过了无损读写坏块测试(耗时 3 天,是的:指定的块大小(-b
)和块数(-c
)很重要)和几次离线 SMART 测试。
为了补充对我的问题的有益贡献,我自己做了一些研究。因为部分结果可能也具有一些普遍意义,所以我在这个自我回答中总结了它们。
请注意:由问题定义,以下所有内容均指
e2fsck
版本 1.41.1,并侧重于没有日志的 Ext2 文件系统。但通用术语也适用于某些扩展,适用于程序和文件系统的当代版本。得到教训
让我们从头条新闻开始——理由如下:
在 C 语言环境中运行
e2fsck
,例如:通过这种方式,您可以获得英文信息,从而更容易在网上找到具体的帮助。
谨慎使用该
-y
选项:它会自动对出现的所有提示回答“是”e2fsck
。这些并不总是指诸如“修复此错误?”之类的问题,还有与要点“删除受影响的文件?”有关的问题。这
e2fsck
对文件系统进行了一些更改并以状态 1(或 3)退出并不意味着存在文件系统错误(损坏)。e2fsck
手柄SIGINT
(Ctrl-C)。但我会避免求助于它。(个人观点。)以下几点侧重于您从中获得的信息
e2fsck
:如果您想知道您的文件系统可能包含哪些错误以及如何
e2fsck
处理它,请不要使用-p
选项 (preen)。与只读 ( ) 或整理 ( ) 运行相比,交互式运行
e2fsck
(即没有选项-n
,-p
,-a
, )会输出更多关于其发现的错误的消息。只是. 从“是”运行 ( ) 中,您获得的信息与交互式运行中的信息基本相同。-y
-n
-p
-a
-p
-y
尽管非常接近,但该选项
-n
不会产生交互式选项的精确试运行。如果您不使用该
-f
选项,则很可能会e2fsck
自行强制检查。这样做,它提供了额外的信息来解释其决定。例子:如果您不想错过这一点,请在没有该选项的情况下开始,如果因为文件系统看起来很干净而拒绝检查
-f
,则仅在第二次尝试中使用它。e2fsck
不要忘记查看退出代码
e2fsck
以获得全貌:echo $?
.支票种类
交互式:不使用选项
-n
、和-p
,执行交互式文件系统检查。这意味着它会在每一步询问您要做什么。这使您可以最大程度地控制该过程。-a
-y
e2fsck
警告:根据文件系统的大小和健康状况,这可能会很快变得乏味:想象一下,您必须逐个 inode 确认修复 inode。这样的会议可能会持续几个小时甚至更糟。
此外,如果问题朝着您不熟悉的方向发展,事情可能会变得非常可怕。
打断:如果交互式检查以这种方式失控,最好知道该
e2fsck
句柄SIGINT
(Ctrl-C)。事实上,有一些令人鼓舞的报道,例如MadHatter和Chris的报道。但正如已经提到的,我会尽量避免这种中断。
原因很简单:检查文件系统是一个复杂的过程,修复损坏必须以连贯一致的方式完成,处理中断更加增加了复杂性。像任何复杂的软件一样,信号处理程序可能有问题。例如,参见Andreas Dilger 的这篇文章。那么为什么要冒险呢?当然可能有很好的理由,但你自己的重量。
只读:如果您对要检查的文件系统的健康状态知之甚少,最好先使用
e2fsck
该-n
选项。正如我们将在下面看到的,这不会产生精确的试运行,但它会给您对交互式运行的期望的良好印象。整理: 如果使用该选项,则
e2fsck
整理文件系统。手册页 e2fsck(8)-p
听起来很有希望:但这也意味着,它只会纠正一些文件系统错误。从 的来源可以看出,一旦检测到无法安全处理的错误
e2fsck
,-p
运行就会停止,将其余部分留给后续运行,而不仅仅是整理。此外,如上所述,
-p
将提供有关错误及其更正的较少信息。是:从选项开始产生
e2fsck
与-y
交互式运行相同的结果,其问题均以“是”回答。上面已经提到了这种方法的缺陷。Expect:正如我从“ Ext2fs Undeletion of Directory Structures mini-HOWTO ”的这一节中了解到的,使用Expect程序可以更精细地自动回答 e2fsck 的问题。在那里,使用了以下包装脚本:
e2fsck
这将自动回答所有使用提示“Clear?”的问题和“n”,以及所有其他的“y”。有关详细信息,请参阅 Expect 的文档。有关使用 expect for 的另一个示例,请参阅Wrothgarr 的这个问题
e2fsck
。澄清一下:我不建议盲目使用这些脚本。此处仅出于“教育目的”引用它们。
对于那些想要接受这个想法并根据自己的需要进行调整的人: 在
e2fsck
源文件 e2fsck/problem.c 的开头附近,定义了一个数组prompt
来保存总共 20 个e2fsck
使用的提示。其中一些仅在内部使用。更多关于提示和文件系统错误之间的相互关系如下。从源头学习
对话框:对于它在文件系统中发现的大多数错误,请
e2fsck
查阅fix_problem
文件 e2fsck/problem.c 中定义的函数。e2fsck
此函数根据给定的选项,根据个别错误执行与用户的对话。为此,在同一文件 e2fsck/problem.c 中先前定义
fix_problem
的数组中查找当前错误代码。problem_table
该数组为每个错误代码赋予了错误消息模板、询问用户问题的提示以及控制错误处理细节的位掩码。(对于某些错误,还引用了另一个错误代码,称为“代码后”,其对话已随后执行。但这对我们来说无关紧要。)在这个位掩码中偶尔使用了两个对我们的问题很重要的标志:
PR_PREEN_NOMSG
和PR_NO_NOMSG
.-p
设置后,它们分别抑制运行和运行的错误消息-n
。因此,这些定义了您在交互式运行或-y
运行中获得更多信息的错误。的定义
problem_table
指定了292个错误代码,其中23个被标记PR_PREEN_NOMSG
,只有1个被标记PR_NO_NOMSG
。它们都没有同时带有标志PR_PREEN_NOMSG
和PR_NO_NOMSG
.另一个有趣的标志是
PR_PREEN_OK
:带有这个标志的错误可以被 preen (-p
runs) 安全地处理。preen 还可以处理其他错误,请参阅下面的“特殊情况”,但这些是其中的大部分。阵列中的 82 个错误problem_table
被标记PR_PREEN_OK
。开始:对于
e2fsck
版本 1.41.1 的 Linux 构建,从main
文件 e2fsck/unix.c 中的函数开始执行。Pass 0:在初始化和检查与这个问题无关的日志之后,对文件系统执行一些基本的检查和清理。这也被称为 pass 0。其中主要部分由
check_super_block
源文件 e2fsck/super.c 中的函数完成。尽管名称如此,但该函数不仅处理超级块,还检查块组描述符。这样做会总结每个块组的空闲块和空闲 inode 计数,并将结果与超级块中的全局值进行比较。
如果这些值不一致会发生什么取决于
e2fsck
命令行选项: 对于-n
运行,文件系统被认为是无效的,稍后会强制进行全面检查。在所有其他情况下(-p
,-y
, 交互式运行),超级块中的总计数会静默更新,而不是强制进行全面检查。事实上,如果后者运行时没有发现额外的错误,它们会报告文件系统是干净的,尽管进行了这种静默更正。该函数
check_super_block
还执行其他操作,例如检查 resize inode、清理孤立 inode、在日志周围进行一些内务管理,但这对于我们的问题似乎并不重要。跳过:
-f
如果选项尚未强制执行完整文件系统检查,e2fsck
我决定自行强制执行完整检查。对此广为人知的标准是自上次检查以来的挂载次数、没有干净卸载、已知文件错误等。但是它还应用了另一个标准,但
-n
前提是未使用该选项:超级块与其备份之间在以下数量方面的差异:启用的文件系统功能,除了
large_file
,dir_nlink
,extent
,总块数,
总索引节点数,
文件系统 UUID。
从这个标准中排除一些文件系统特性的原因是内核可以根据需要动态设置这些特性,并且只在超级块中而不是在备份中这样做。对于例外功能,此类差异被认为不够重要,无法强制进行全面检查。相反,该
ext_attr
功能也可能由内核动态设置,但在这种情况下,备份中的更新至关重要,为什么不排除此功能。如果
e2fsck
决定由 ts 自己强制进行全面检查,它会打印一条消息以说明不便之处。如果这是由于超级块与其备份之间的命名差异之一,则消息显示为:请注意,消息中的术语“功能”比纯粹的“文件系统功能”具有更广泛的含义:例如,它还涵盖了总块数。在这方面,另请参阅Eric Sandeen 的这篇文章和Theodore Tso 的这篇文章。
无论如何,您永远不会在
-n
运行中看到此消息,因为如上所述,在这种情况下不考虑超级块备份。如果未强制进行完整检查,无论是 by
-f
还是 bye2fsck
,都将跳过检查(e2fsck
字典)。在这种情况下,e2fsck
将文件系统报告为 clean end exits,状态为 0。如果在 pass 0 中有一些修复,例如修正超级块中的总空闲块数,这也是正确的。Passes 1 到 6:在全面检查
e2fsck
中,至少完成五次完整的文件系统遍历,每一次都有不同的焦点。这些分别由源文件 e2fsck/pass1.c 到 e2fsck/pass5.c 中定义的函数e2fsck_pass1
执行e2fsck_pass5
。如果需要处理特殊的文件系统损坏,可能会有额外的通道来补充通道 1。这些标记为 pass 1B to pass 1D,相应的函数
pass1b
都pass1d
定义在 e2fsck/pass1b.c 中。e2fsck_rehash_directories
目录的重新散列是第 3 步的一部分,由文件 e2fsck/rehash.c 中的函数执行,被视为第 3A 步。此外,
PR_6_RECREATE_JOURNAL
当必须重新创建日志时,还会使用一个错误代码。显然这被认为构成了一个单独的 pass:pass 6。它是在 function 中执行的main
。problem_table
在这些遍中检查数组中定义的大多数错误。对于每个错误,可以从其错误代码的名称中看到它所经历的通过次数:数字跟在代码名称中的第一个下划线之后。因此,例如,错误PR_1_TOO_MANY_BAD_BLOCKS
在通道 1 中处理,并PR_3A_OPTIMIZE_DIR_ERR
在通道 3A 中得到处理。对于这个问题特别感兴趣的是,在第 5 步开始时再次检查空闲块和空闲 inode 的总数:除了在第 0 步中的快速检查,其中只有块组描述符中的相应值是总而言之,这次计数是根据在
e2fsck
其通过完整文件系统的过程中彻底收集的数据计算的,在该文件系统中,每个块和每个 inode 的角色都被单独分析。这是由文件 e2fsck/pass5.c 中定义check_block_bitmaps
的函数完成的。check_inode_bitmaps
结果值与超级块中的值相比的差异被视为错误
PR_5_FREE_BLOCK_COUNT
和PR_5_FREE_INODE_COUNT
。顺便说一句,这些错误已被标记PR_PREEN_NOMSG
,因此在整理 (-p
) 时不会明确报告它们。特殊情况:可能会在文件系统上执行更正,
e2fsck
而无需调用fix_problem
或查阅problem_table
. 这些更正仅在没有-n
选项的情况下执行,并且在输出中没有通知,但可能处于退出状态。我在来源中找到了其中三个:-n
在第 0 遍(不带)期间,对超级块中的总空闲块和空闲 inode 计数的更正。这已经在上面讨论过了。在第 1 遍期间,如果设置(不带 ),超级块中的最后一个孤立字段会被静默清除
-n
。如果存储在索引目录的 inode 中的链接计数值表明它先前超过了其上限,而当前的真实计数低于此限制,则 inode 中的值在第 4 步中被静默纠正(没有
-n
)。退出状态:对于完全(强制)检查,退出代码由函数
main
在检查完成后在分析后者结果的过程中确定:如果检查没有中途取消,则退出状态为零,如果并且只有在到目前为止文件系统没有更改的情况下。最后一点:如果检查没有在中途取消,该函数会
main
重置超级块中的挂载计数并更新那里的时间戳,以便e2fsck
在以后的运行中知道何时必须强制执行下一次完整检查。这是在确定退出状态后的清理期间完成的,因此此更改对状态没有影响。信号处理程序:在由
PRS
调用的函数中main
,都在 e2fsck/unix.c 中定义,为、、和e2fsck
生成信号处理程序。后两者可用于切换进度信息,如手册页 e2fsck(8)中所述。SIGINT
SIGTERM
SIGUSR1
SIGUSR2
前者显然被处理以允许安全中断和终止
e2fsck
.从测试中学习
Trying to reproduce the behavior of
e2fsck
that is shown in the question, I set up a test Ext2 filesystem, populated it with dummy files up to 10% of its capacity, and used a hex editor to introduce some artificial errors. Then that filesystem was checked with the same commands as in the question to compare outputs and exit statuses ofe2fsck
.In the last run in the question, the count of used blocks has changed.
e2fsck
calculates this value in an obvious way from the free block count and the total blocks count. That is why I chose these quantities as the subject of the artificial errors.Free blocks count in superblock: The data structure of the superblock is described in great detail in this document. (A contemporary version of this document, which describes the Ext4 filesystem, can be found here.) Based on that, I used the hex editor to reduce the free blocks count in the superblock by 2.
This artificial error was detected by
e2fsck -nv
(without-f
) which complained loudly, forced a full check and exited with exit status 4.Also a forced read-only run (
-nfv
) reported that error and exited with status 4.A subsequent
-pv
run (without-f
) found the filesystem clean and did not give any notice about an error. However, it corrected the error and output the number of used blocks based on the corrected values, yet exited with status 0.After introducing the same error again, a forced preen run (
-pfv
) was also not reporting the error, but corrected it exiting with status 1.This behavior of
e2fsck
can be well understood from what was learned from the sources, above.This means, that it must have been a different error that led to the check results described in the question: Otherwise, it would have been reported by the read-only runs and corrected by the first (unforced) preen, so that the last run would have found a clean filesystem.
Total blocks count in superblock: Using a hex editor, I reduced the total blocks count in the superblock by 2.
This was not detected by an
-nv
run (without-f
), which reported the filesystem as clean and exited with status 0.Forcing this check (
-nfv
), several errors were found—wrong ones in a sense:e2fsck
took the manipulated total block count seriously, and found in consequence wrong free blocks counts in the last block group and in the superblock. In addition, it found that the padding at the end of the block bitmap was not set. The exit status was 4.A subsequent preening (
-pv
, without-f
) forced a full check because of differences between the superblock and it backups. In the course, it corrected all the "wrong" errors that were previously found by the forced read-only run. However, it only reported the ("wrong") error in the bitmap padding, not giving any notice on the free blocks counts. It finally exited with status 1.After introducing the same error again, a forced preening (
-pfv
) did essentially the same, except that is did not inform about the difference between the superblock and it backups that was previously given as the reason for the forced check.Also this behavior of
e2fsck
can be understood from the discussion of the sources above. It was, however, different from what is described in the question. So it must have been another error there.Free blocks count in backup: The block numbers of the superblock backups can be found with
However, the free blocks count in the first superblock backup is totally ignored by
e2fsck
. In fact, it seems that this value differs from that in the primary superblock even in a truly clean filesystem. And indeed, if one thinks about it, it would be a huge overhead to keep this value constantly synchronized throughout all the backups. So I assume, that there it has no meaning at all.Total blocks count in backup: Using the hex editor again, I reduced the total blocks count in the first superblock backup by 2.
This artificial error was totally ignored by
e2fsck
in read-only mode:-nv
and-nfv
.A preen run (
-pv
, without-f
) forced a full check giving the messageIn the course, it corrected the error without further related messages and exited with status 1.
After introducing the same error again, a forced preening (
-pfv
) did the same, yet without any notice on the error.Again, this behavior can be well understood from the above discussion of the sources; and it is different from what was observed in the question.
In addition, the unforced
e2fsck
runs described in the question and the subsequently performed checks described in update 1 reported the same total blocks count. So this value was not changed in any of these runs and hence could not be the subject of the wanted error.Does this yield an answer to the question?
In short: No.
For each individual run that is described in the question, I found possible errors that lead to the observed behavior of
e2fsck
. But I did not find a single error that causes that behavior of all runs in a sequence.All errors in
problem_table
are ruled out, because they would have been reported either by the-nfv
run or by the-pfv
run or by both.Considering the "special cases" above, a wrong free blocks or free inodes count would have been reported by the read-only runs. This was not the case.
The other "special cases" would not have led to a change of the used blocks count that was observed in the last run.
But after all,
e2fsck
is a complex piece of software, so it is most likely that I have overseen something.Result
Facing these findings, it seems that the following workflow can be used to safely check an unmounted Ext2 filesystem with unknown health status while avoiding unpleasant surprises in the interactive part and getting a maximum of information from
e2fsck
.This assumes a healthy hardware! If in particular the drive is not trustworthy in this respect, unconditionally begin with step 3 (back up the filesystem), proceeding with the remaining steps in the stated order:
Do an
-nv
run:If
e2fsck
skips the full check reporting the filesystem as clean, force the check repeating step 1 with-f
.Depending on the corruptions found, back up the filesystem with
dd
. This allows to restore the current state if things get screwed up in the next steps.If it seems feasible according to the results of the read-only runs, do an interactive check with
forcing it with
-f
if needed to get a full check.What to do if an interactive run is not feasible depends on the findings so far.
Appendix: Inspecting filesystem features
dumpe2fs: The program
dumpe2fs
can be used to find out which features are enabled in a filesystem.This does also work for unknown features. In this case,
dumpe2fs
uses generic feature names that uniquely identify the corresponding bits in the features fields of the superblock. For exampleFEATURE_R16
corresponds to bit 16 (counting from 0) in the read-only compatible features field of the superblock. Similarly,FEATURE_I31
corresponds to the most significant bit of the incompatible features field.If the feature
compression
is set,dumpe2fs
has to be started with the-f
option.However, version 1.41.1 of this program seems to be a little bit buggy, as it crashes with a floating point exception on some combinations of enabled and disabled features, e.g. for enabled
64bit
and disabledjournal_dev
.debugfs: The command
show_super_stats
ofdebugfs
yields a similar output to that ofdumpe2fs
with regard to the enabled filesystem features. Also this program informs about unknown features.The version 1.41.1 also of this program seems to be somehow buggy: The command
show_super_stats
crashes with a segmentation fault ifcompression
orjournal_dev
is enabled. Likedumpe2fs
, the whole programdebugfs
crushes with a floating point exception if the feature64bit
is enabled whilejournal_dev
is disabled.tune2fs: If only known filesystem features are enabled, they can be listed as part of the output of
tune2fs -l
. However, this program refuses to start if any unknown filesystem feature is enabled, even if the-f
option is used.您提到此文件系统用于非常旧的机器。如果文件系统最初是用一个非常旧的
mke2fs
工具创建的,该工具不支持resize_inode
文件系统功能来为文件系统的在线扩展保留一些元数据空间,那么您使用 1.14.1 版本的第二次运行可能e2fsck
只是自动添加它.如果我没记错的话,分配对于不理解它的旧系统来说是完全良性的,但是如果文件系统被扩展,它可以确保一些关键的元数据结构可以在没有重大重组的情况下扩展。
您可以通过
tune2fs -l
在 USB 驱动器的文件系统和旧机器的 ext2 文件系统之一上运行并比较结果来确认这一点。即使文件系统已挂载,您也可以这样做。如果您的 USB 驱动器的输出包含该行中的关键字resize_inode
,Filesystem features:
而您的旧机器上的本地 ext2 文件系统没有该关键字,那么最可能的解释是您e2fsck -pfv
只是希望借此机会进行微小的分配它可能有助于避免将来出现停机。