SSD驱动器的ext3分区上的突然掉电后文件系统损坏是“预期行为”吗?


13

我公司制造了一个嵌入式Debian Linux设备,该设备从内部SSD驱动器上的ext3分区启动。因为该设备是嵌入式“黑匣子”,所以通常通过简单地通过外部开关切断设备电源来粗鲁地关闭它。

这通常是可以的,因为ext3的日志记录可以使事情井井有条,因此,除了偶尔丢失部分日志文件外,事情还可以继续进行。

但是,我们最近看到了许多单元,在经过多次硬重启之后,ext3分区开始出现结构性问题-特别是,我们在ext3分区上运行e2fsck,它发现了许多类似的问题显示在此问题底部的输出清单中。运行e2fsck直到停止报告错误(或重新格式化分区),都可以解决问题。

我的问题是...在遭受大量突然/意外关机的ext3 / SSD系统上看到类似问题的含义是什么?

我的感觉是这可能是我们系统中软件或硬件问题的迹象,因为我的理解是ext3的日记功能(除非存在错误或硬件问题)被认为可以防止这类文件系统完整性错误。(注意:我了解用户数据未记录日志,因此用户文件可能被蒙蒙/丢失/截断;我在这里专门谈论文件系统元数据错误,如下所示)

另一方面,我的同事说这是已知的/预期的行为,因为SSD控制器有时会重新排序写命令,这可能会使ext3日志感到困惑。特别是,他认为,即使给定了正常运行的硬件和无错误的软件,ext3日志也只会减少文件系统损坏的可能性,这并非不可能,因此我们不时看到这样的问题也不会感到惊讶。

我们哪个是对的?

Embedded-PC-failsafe:~# ls
Embedded-PC-failsafe:~# umount /mnt/unionfs
Embedded-PC-failsafe:~# e2fsck /dev/sda3
e2fsck 1.41.3 (12-Oct-2008)
embeddedrootwrite contains a file system with errors, check forced.
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Invalid inode number for '.' in directory inode 46948.
Fix<y>? yes

Directory inode 46948, block 0, offset 12: directory corrupted
Salvage<y>? yes

Entry 'status_2012-11-26_14h13m41.csv' in /var/log/status_logs (46956) has deleted/unused inode 47075.  Clear<y>? yes
Entry 'status_2012-11-26_10h42m58.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47076.  Clear<y>? yes
Entry 'status_2012-11-26_11h29m41.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47080.  Clear<y>? yes
Entry 'status_2012-11-26_11h42m13.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47081.  Clear<y>? yes
Entry 'status_2012-11-26_12h07m17.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47083.  Clear<y>? yes
Entry 'status_2012-11-26_12h14m53.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47085.  Clear<y>? yes
Entry 'status_2012-11-26_15h06m49.csv' in /var/log/status_logs (46956) has deleted/unused inode 47088.  Clear<y>? yes
Entry 'status_2012-11-20_14h50m09.csv' in /var/log/status_logs (46956) has deleted/unused inode 47073.  Clear<y>? yes
Entry 'status_2012-11-20_14h55m32.csv' in /var/log/status_logs (46956) has deleted/unused inode 47074.  Clear<y>? yes
Entry 'status_2012-11-26_11h04m36.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47078.  Clear<y>? yes
Entry 'status_2012-11-26_11h54m45.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47082.  Clear<y>? yes
Entry 'status_2012-11-26_12h12m20.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47084.  Clear<y>? yes
Entry 'status_2012-11-26_12h33m52.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47086.  Clear<y>? yes
Entry 'status_2012-11-26_10h51m59.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47077.  Clear<y>? yes
Entry 'status_2012-11-26_11h17m09.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47079.  Clear<y>? yes
Entry 'status_2012-11-26_12h54m11.csv.gz' in /var/log/status_logs (46956) has deleted/unused inode 47087.  Clear<y>? yes

Pass 3: Checking directory connectivity
'..' in /etc/network/run (46948) is <The NULL inode> (0), should be /etc/network (46953).
Fix<y>? yes

Couldn't fix parent of inode 46948: Couldn't find parent directory entry

Pass 4: Checking reference counts
Unattached inode 46945
Connect to /lost+found<y>? yes

Inode 46945 ref count is 2, should be 1.  Fix<y>? yes
Inode 46953 ref count is 5, should be 4.  Fix<y>? yes

Pass 5: Checking group summary information
Block bitmap differences:  -(208264--208266) -(210062--210068) -(211343--211491) -(213241--213250) -(213344--213393) -213397 -(213457--213463) -(213516--213521) -(213628--213655) -(213683--213688) -(213709--213728) -(215265--215300) -(215346--215365) -(221541--221551) -(221696--221704) -227517
Fix<y>? yes

Free blocks count wrong for group #6 (17247, counted=17611).
Fix<y>? yes

Free blocks count wrong (161691, counted=162055).
Fix<y>? yes

Inode bitmap differences:  +(47089--47090) +47093 +47095 +(47097--47099) +(47101--47104) -(47219--47220) -47222 -47224 -47228 -47231 -(47347--47348) -47350 -47352 -47356 -47359 -(47457--47488) -47985 -47996 -(47999--48000) -48017 -(48027--48028) -(48030--48032) -48049 -(48059--48060) -(48062--48064) -48081 -(48091--48092) -(48094--48096)
Fix<y>? yes

Free inodes count wrong for group #6 (7608, counted=7624).
Fix<y>? yes

Free inodes count wrong (61919, counted=61935).
Fix<y>? yes


embeddedrootwrite: ***** FILE SYSTEM WAS MODIFIED *****

embeddedrootwrite: ********** WARNING: Filesystem still has errors **********

embeddedrootwrite: 657/62592 files (24.4% non-contiguous), 87882/249937 blocks

Embedded-PC-failsafe:~# 
Embedded-PC-failsafe:~# e2fsck /dev/sda3
e2fsck 1.41.3 (12-Oct-2008)
embeddedrootwrite contains a file system with errors, check forced.
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Directory entry for '.' in ... (46948) is big.
Split<y>? yes

Missing '..' in directory inode 46948.
Fix<y>? yes

Setting filetype for entry '..' in ... (46948) to 2.
Pass 3: Checking directory connectivity
'..' in /etc/network/run (46948) is <The NULL inode> (0), should be /etc/network (46953).
Fix<y>? yes

Pass 4: Checking reference counts
Inode 2 ref count is 12, should be 13.  Fix<y>? yes

Pass 5: Checking group summary information

embeddedrootwrite: ***** FILE SYSTEM WAS MODIFIED *****
embeddedrootwrite: 657/62592 files (24.4% non-contiguous), 87882/249937 blocks
Embedded-PC-failsafe:~# 
Embedded-PC-failsafe:~# e2fsck /dev/sda3
e2fsck 1.41.3 (12-Oct-2008)
embeddedrootwrite: clean, 657/62592 files, 87882/249937 blocks

你们是否都考虑过要改用ext4或ZFS?
mdpc

我已经考虑过至少要改用ext4 ...这是否有助于解决这个问题?ZFS还会更好吗?
Jeremy Friesner

1
两种方法都不能解决这个问题。我们仍然在ZFS中使用带有超级电容器的设备,并且在服务器应用程序中为ext4建议使用电池或闪存保护的缓存。
ewwhite

Answers:


11

你们都错了(也许吗?)... ext3可以最大限度地应对,因为它突然删除了其底层存储。

您的SSD可能具有某种类型的板载缓存。您没有提及正在使用的SSD的型号/型号,但这听起来像是消费者级SSD与企业工业级型号

无论哪种方式,都可以使用缓存来帮助合并写入并延长驱动器的寿命。如果在途中有写入,突然断电肯定是造成腐败的原因。真正的企业和工业SSD具有超级电容器,它们可以维持足够长的时间来将数据从缓存移至非易失性存储,这与电池备份和闪存备份RAID控制器缓存的工作方式大同小异。

如果驱动器没有超级电容,则正在运行的事务将丢失,因此文件系统损坏。ext3可能被告知一切都在稳定的存储中,但这只是缓存的功能。


抱歉,您和所有对此表示支持的人,但是您错了。处理正在进行的写入丢失恰恰是日志的目的,并且只要驱动器正确地报告它是否具有写缓存并遵守刷新命令的命令,日志就会保证元数据不会不一致。您只需要超级电容器或电池供电的RAID缓存,因此无需启用障碍即可启用写缓存,这会牺牲一些性能来保持数据正确性。
psusi

@psusi正在使用的SSD可能已显式启用了缓存,或者依赖于内部缓冲区,而不管OS_level设置如何。该高速缓存中的数据就是启用超级电容器的SSD可以保护的数据。
ewwhite 2012年

如果启用IO屏障,则不需要保护缓存中的数据。大多数使用者类型的驱动器默认情况下都禁用写缓存,因此您必须启用它,这完全是因为如果操作系统不小心会导致损坏问题。
psusi

2
@pusi现在很旧,但是您提到了这一点:as long as the drive correctly reports whether it has a write cache and obeys commands to flush it, the journal guarantees that the metadata will not be inconsistent.就是这样:由于存储控制器倾向于使用旧磁盘,因此SSD 有时取决于是否刷新数据。您确实需要那个超级电容。
Joel Coel 2015年

2

你是正确的,你的同事是错误的。除非出现错误,否则日记将确保您永远不会出现不一致的fs元数据。您可以检查hdparm以查看驱动器的写缓存是否已启用。如果是这样,并且您尚未启用IO屏障(在ext3上默认关闭,在ext4上默认打开),则可能是问题的原因。

需要使用障碍来强制驱动器写高速缓存在正确的时间刷新以保持一致性,但是某些驱动器的行为很差,它们要么报告其写高速缓存在未启用时被禁用,要么静默忽略刷新命令。这样可以防止日记工作。


-1为阅读理解……
ewwhite

@ewwhite,也许应该尝试阅读,并实际写出一个有用的答案,而不是这种幼稚的侮辱。
psusi

与任何质量检查中的其他任何答案一样,该答案可能需要+1。但是至少提供了一些提示。@downvoters:自己改善答案,或对可能的流程发表评论,但是在没有正当理由的情况下降低答案的答案简直令人恶心!
阿尔贝托
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.