崩溃后,e2fsck 失败,块数量/大小异常高

崩溃后,e2fsck 失败,块数量/大小异常高

断路器跳闸后,我的 Raspberry Pi 开始因内核恐慌而停止启动(与这里)。这是一个运行 Raspbian 的 Raspberry Pi,因此它从 SD 卡的主ext4分区运行,我尝试使用以下方法在我的 PC 上修复该分区:

sudo e2fsck -f -y -v /dev/sdx2

然而,这最终失败并出现一些奇怪的输出:

Error writing block 137439060017 (Invalid argument) while getting next inode from scan.  Ignore error? yes
Error reading block 183472412950529 (Invalid argument).  Ignore error? yes
Force rewrite? yes
Error writing block 183472412950529 (Invalid argument) while getting next inode from scan.  Ignore error? yes
Inode 13329, i_size is 4096, should be 549755817984.  Fix? yes
Inode 13607, i_size is 69632, should be 137439023104.  Fix? yes
Error reading block 36983963385857 (Invalid argument).  Ignore error? yes
Force rewrite? yes
Error writing block 36983963385857 (Invalid argument) while getting next inode from scan.  Ignore error? yes
Error reading block 179632729097217 (Invalid argument).  Ignore error? yes
Force rewrite? yes
Error writing block 179632729097217 (Invalid argument) while getting next inode from scan.  Ignore error? yes
Error reading block 17592186080054 (Invalid argument) while reading directory block.  Ignore error? yes
Force rewrite? yes
Error writing block 17592186080054 (Invalid argument) while getting next inode from scan.  Ignore error? yes
Error storing directory block information (inode=17449, block=0, num=134507168): Memory allocation failed
/dev/sdx2: ***** FILE SYSTEM WAS MODIFIED *****
e2fsck: aborted
/dev/sdx2: ***** FILE SYSTEM WAS MODIFIED *****

这里有两件事令人担忧:

  • inode 大小和块大小,看起来高得离谱(我们谈论的是 16GB SD 卡),
  • e2fsck结尾为Memory allocation failed- 在具有 32 GB RAM 的 PC 上,其中大部分是免费的。它实际上在失败之前占用了可用 RAM。

我尝试配置一个临时文件目录,得到相同的结果(e2fsck确实在那里写入了一些文件,并且目标目录位于具有 +250GB 可用空间的挂载上 - 它占用了可用 RAM,并且失败)。

受影响分区上的基本文件系统参数似乎存在一些损坏。如何诊断并消除呢?

答案1

当您运行 e2fsck -fy 时,您确实需要保存整个 e2fsck 记录,而不仅仅是显示最后几条错误消息。可能文件系统损坏得很严重,-y 选项意味着无论如何都要继续。

看起来块组描述符已严重损坏,因此 inode 表的位置很疯狂。 E2fsck 可能尝试修复它,但由于某种原因它无法修复它,“-y”意味着尽管如此它仍会继续运行。因此,当人们发送错误报告时,我总是建议他们发送完整的 e2fsck 记录,而不仅仅是最后几个错误。

答案2

我快速浏览了一下e2fsck源,在我看来,有些地方“内存分配失败”发生错误的原因可能实际上并不是内存分配错误。

错误字符串是[src]/lib/ext2fs/ext2_err.et.in相对于常量定义的EXT2_ET_NO_MEMORY。这可以从 中代码中的各个位置返回[src]/e2fsck/。这是来自的示例ea_refcount.c

errcode_t ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
{
    struct ea_refcount_el   *el;

    el = get_refcount_el(refcount, blk, 1);
    if (!el)
        return EXT2_ET_NO_MEMORY; 

get_refcount_el()位于同一个文件中:

static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
                          blk_t blk, int create)
{
    int low, high, mid;

    if (!refcount || !refcount->list)
        return 0;    

这不是它返回 null 的唯一原因,也不是看起来与失败的分配没有直接关系的唯一原因。

要真正证明我必须进行更多挖掘,但这确实符合您的说法,即它并没有真正耗尽系统内存。

在这种情况下,也许问题与混乱/损坏的 SD 卡控制器的模糊且不可预测的潜力有关,但它仍然相当于 e2fsck 中的一个错误,因为需要进行某种健全性检查或采取其他措施来捕获此问题,即使只是说“对不起,你的设备坏了”(可能是真的)与“内存不足”(可能不是真的)。您可能想要报告此问题(“如果这些程序出现错误,请联系 Ted Ts'o:[电子邮件受保护]或者[电子邮件受保护]-- 我相信TT是一个linux内核开发者),你可以参考这个Q&A。

除此之外,在我看来,你最好忘记该卡上的任何内容,并对它进行破坏性的读写测试:

badblocks -v -w -b 1048576 -c 16 /dev/sdx

请记住,这是一个破坏性的测试——您将丢失所有数据。 Badblocks 对于为 SD 卡创建实际的坏块列表没有用处(由于磨损均衡,它们不报告实际的物理地址),但如果卡坏了,它可能会让您知道。以这种方式测试 16 GB 卡只需不到一个小时。

相关内容