低内存机器上的 e2fsck:我可以从 scratch_files 或 swap 中获得更多吗?

低内存机器上的 e2fsck:我可以从 scratch_files 或 swap 中获得更多吗?

我在具有 1 GB RAM 的 32 位机器上运行 CentOS 6。

我有一个 1TB 的外置硬盘,我想在上面运行 e2fsck。它运行了大约一个半小时,然后失败了Error storing directory block information (inode=45206324, block=0, num=39291127): Memory allocation failed。在发现这个问题, 我创建/etc/e2fsck.conf根据指示的内容创建了这个问题,创建了一个 20GB 的交换文件(我只有一个磁盘,因此无法将交换文件拆分到多个磁盘上)。交换空间已经有 2GB 了。

发生故障时,其 scratch_files 目录中已占用约 325MB 空间,交换使用量为 550MB。新的 20GB 交换文件未受影响。它又挂起 45 分钟,CPU 使用率约为 2%,然后程序死机,e2fsck: aborted交换量又回到约 65MB。

使用iostat -dx,我发现当 e2fsck 仍在运行(但失败)时,主磁盘的利用率为 4.3%,外部驱动器的利用率为 7.2%,但我没有在 CPU 达到 100% 时运行此操作,所以我不知道情况如何。程序最终中止后,这些磁盘利用率数字没有变化。

所以我的问题是:为什么 e2fsck 会失败,既没有用尽交换空间,也没有用临时文件填满磁盘?我还能尝试用这台机器修复这个磁盘吗?它离我们有 3000 英里远……

编辑:top以下是内存故障之前 与内存相关的行:

Mem:   1029080k total,  1010780k used,    18300k free,   309780k buffers
Swap: 23019504k total,    71796k used, 22947708k free,   433072k cached

之后,仍在运行:

Mem:  1004.961M total,  991.344M used,   13.617M free, 1728.000k buffers
Swap:   21.953G total,  541.621M used,   21.424G free,   27.949M cached

编辑2

e2fsck再次使用运行strace。有趣的是,它可以运行更长时间,占用了大约 220 分钟的 CPU 时间,同时使用率约为 70%(stracetail占用了其余 30%)。该程序占用了 1832 MB 的虚拟内存、811 MB 的常驻内存和 105 MB 的共享内存。以下是strace失败的内存分配中的几行:

22648 mremap(0x32ebc000, 1675546624, 2513317888, MREMAP_MAYMOVE) = -1 ENOMEM (Cannot allocate memory)
22648 mmap2(NULL, 2513317888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
22648 mmap2(NULL, 2513453056, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
22648 mmap2(NULL, 2097152, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0xb2ca5000
22648 munmap(0xb2ca5000, 372736)        = 0
22648 munmap(0xb2e00000, 675840)        = 0
22648 mprotect(0xb2d00000, 135168, PROT_READ|PROT_WRITE) = 0
22648 mmap2(NULL, 2513317888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)

读取和写入似乎没有发生任何奇怪的事情:

22648 _llseek(3, 755934822400, [755934822400], SEEK_SET) = 0
22648 write(3, "/\276\0\0|}\33xA\236\0d/\243\0\0A\236\0\\\0\0\0\0\177\303\363x8\200\0\4"..., 4096) = 4096
22648 lseek(3, 260845568, SEEK_SET)     = 260845568
22648 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
22648 _llseek(3, 755934793728, [755934793728], SEEK_SET) = 0
22648 write(3, "\376\355\372\317\1\0\0\22\0\0\0\0\0\0\0\6\0\0\0\23\0\0\0\0\0\21\0\205\0\0\0\0"..., 4096) = 4096
22648 write(1, "I", 1)                  = 1
22648 write(1, "node", 4)               = 4
22648 write(1, " ", 1)                  = 1
22648 write(1, "46217250", 8)           = 8
22648 write(1, " is too big.  ", 14)    = 14
22648 write(1, "Truncate? yes\n\n", 15) = 15

答案1

我不是 e2fsck 专家。我认为 e2fsck 确实关心它看到的内存是真实 RAM 还是交换。页面可以锁定到内存中。我假设可以通过 /proc 或 ps、top 等获取锁定内存量的信息。您可以监视此值。

显然,唯一好的解决方案是将磁盘连接到更好的硬件。这对您来说很难。但通过网络而不是物理连接甚至可能有所帮助。如果有另一个 Linux 系统与您的系统有合适的 LAN 连接并且有更多的 RAM,那么您可以将要检查的设备导出为网络块设备。可能仍然比我的下一个想法更快。

如果问题是 e2fsck 需要“真实”RAM,那么您可以创建一个带有小型 Linux 安装的虚拟机(除了 e2fsck 之外不需要其他任何东西……)。此 VM 可以配置 2、4、16 GiB 的“RAM”。要检查的设备可以导出为块设备(在 VM 中显示为磁盘)。无论如何,使用 scratch_files 功能可能很有意义。这显然会是一场性能噩梦,但我想您已经接受了此类别中的任何可能解决方案。

编辑1

您可以通过以下方式查看进程已锁定到 RAM 中的虚拟内存量:

grep VmLck /proc/$PID/status

编辑2

以下是dmesg与设备相关的所有内容sdb。错误是我首先EXT4-fs运行的原因。e2fsck

sd 0:0:0:0: [sdb] 1953525168 512-byte logical blocks: (1.00 TB/931 GiB)
sd 0:0:0:0: [sdb] Write Protect is off
sd 0:0:0:0: [sdb] Mode Sense: 28 00 00 00
sd 0:0:0:0: [sdb] Assuming drive cache: write through
sd 0:0:0:0: [sdb] Assuming drive cache: write through
 sdb: sdb1
sd 0:0:0:0: [sdb] Assuming drive cache: write through
sd 0:0:0:0: [sdb] Attached SCSI disk
EXT4-fs (sdb1): barriers disabled
EXT4-fs (sdb1): warning: mounting fs with errors, running e2fsck is recommended
EXT4-fs (sdb1): recovery complete
EXT4-fs (sdb1): mounted filesystem with ordered data mode. Opts: 
SELinux: initialized (dev sdb1, type ext4), uses xattr
EXT4-fs error (device sdb1): ext4_lookup: deleted inode referenced: 46006273
EXT4-fs (sdb1): ext4_check_descriptors: Checksum for group 0 failed (2332!=0)
EXT4-fs (sdb1): group descriptors corrupted!
EXT4-fs (sdb1): ext4_check_descriptors: Checksum for group 0 failed (34754!=0)
EXT4-fs (sdb1): group descriptors corrupted!
EXT4-fs (sdb1): ext4_check_descriptors: Checksum for group 0 failed (34754!=0)
EXT4-fs (sdb1): group descriptors corrupted!

答案2

我们可以看出,e2fsck 正在尝试为它试图提出的任何表分配 2.5gb,并且即使你有足够的(虚拟)RAM 可用,但在 32 位进程中你也没有用于该地址的地址空间。

嗯,是的但是您一次请求其中的 5/6,很可能其他映射/分配之前已经占用了剩余的 500mb 地址空间,因此内核无法找到连续的 2.5gb 空间来满足 mmap2。

我的建议是:尝试运行可通过 USB 启动的 64 位 Linux,使用您拥有的相同 20gb 交换文件(或至少有 4gb 的交换文件),您已经知道这可能需要很长时间才能完成。

附注:我下载了 e2fsprogs 源代码来确定 e2fsck 是否可以通过调用 mlock() 或 mlockall() 来请求真实 RAM,但递归搜索“mlock”没有结果,因此这条路径似乎不太可能。

我无法对帖子发表评论(我是新来的),如果有用的话请点赞我的回答,这样我就可以获得 serverfault 要求的声誉点数,让我可以对帖子发表评论。

最后,但并非最不重要的一点是:你可以使用 strace 来跟踪所有与内存相关的调用strace -e 内存 e2fsck..

相关内容