导致I / O错误的特殊文件


13

如果要读取的基本SQLite DB文件失败(导致I / O错误),我想自动测试某个软件是否响应预期。确实是几天前在客户那里发生的。我们手动修复了它,但是现在我想创建自动代码来修复它,并且需要访问损坏的文件来进行测试。

由于Unix中的所有内容都是一个文件,因此我怀疑可能存在一个特殊文件,当尝试读取该文件时总是会导致I / O错误(例如,在/ dev中)。

一些类似的文件(imo)将是:

  • /dev/full 如果您尝试写入,则始终显示“设备上没有剩余空间”
  • /dev/null/dev/zero

所以我认为只需要有一个这样的文件(但是还没有找到)。

有谁知道这样的文件或任何其他方法可以让我获得所需的结果(故意有问题的分区图像,使用LD_PRELOAD封装open()的包装程序,等等)?
去这里最好的方法是什么?


据我所知,Linux上没有特殊文件可以在您读取SIGIO时使用。我上次获得SIGIO的原因是USB记忆棒宣称其容量比实际的物理记忆棒大得多。也许有可能吗?
lgeorget

嗯,我也许可以尝试使用一个较小的分区映像进行尝试,然后将其裁剪在中间的某个位置...
mreithub

SIGIO并不意味着出现错误,它是一种程序可以请求通知现在可以进行非阻塞IO的方式,而不是调用select()或poll()。
psusi

Ups,是的,您当然是对的。我写了SIGIO,但正在考虑EIO错误代码。但也许是OP?为什么读取失败会导致SIGIO?
lgeorget

哦,我在这个问题上犯了同样的错误...对其进行了编辑...
mreithub,

Answers:


8

您可以使用或目标来dmsetup创建设备映射器设备,以模拟故障。errorflakey

dmsetup create test --table '0 123 flakey 1 0 /dev/loop0'

其中123是设备的长度(以扇区为单位),/ dev / loop0是要在其上模拟错误的原始设备。对于错误,您不需要后续参数,因为它总是返回错误。


1
我在该命令中发现至少两个错误:丢失的设备名称,双引号和“ 1 0 / dev / null”是什么意思?
Hauke Laging

@HaukeLaging,嗯,是的,我省略了名称,并以某种方式打错了报价。1 0 / dev / null表示1个目标,从偏移量0开始,由设备/ dev / null支持。flakey是必需的,但显然对于错误是可选的。
psusi

在我看来,它不是“可选”的,只是被忽略了。您可以通过进行确认dmsetup table test。你甚至可以写foo bar在后面error; 它只是不在乎(因此应删除)。
Hauke Laging

@HaukeLaging,已编辑。
psusi

感谢您的回答,我认为这就是我现在要走的路。我唯一的小问题是它需要root访问,但是我想无论如何还是这样的低级工作……(我有空的时候我会深入研究LD_PRELOAD的想法)。
mreithub

14

关于堆栈溢出和服务器故障,已经有很多答案,但是缺少一些技术。为了使生活更轻松,这是VM / Linux块设备/ Linux文件系统/ Linux用户空间库I / O故障注入机制的列表:

奖励事实:SQLite具有用于模拟错误的VFS驱动程序,因此可以获得良好的测试覆盖率。

有关:


5

您需要I / O 的故障注入机制。

在Linux上,以下方法不需要任何预先设置即可生成异常错误(不是EIO“输入/输出错误”,而是ESRCH“无此类过程”):

cat /proc/1234/mem

其中1234是与您要测试的进程以同一用户身份运行的进程的PID,但不是该进程本身。学分rubasov思考/proc/$pid/mem

如果您使用流程本身的PID,则将获得EIO,但前提是您正在从未在流程内存中映射的区域读取数据。第一页从不映射,因此可以按顺序读取文件,但是不适合直接查找文件中间的数据库进程。

通过以root用户身份进行更多设置,您可以利用设备映射器来创建具有有效扇区和坏扇区的文件。

另一种方法是实现小型FUSE文件系统。当您的用户空间文件系统驱动程序发生错误时,EIO是默认的错误代码,因此很容易实现。无论是Perl的Python的绑定来举例上手,您可以快速编写大多镜子现有的文件,但一个内喷射在EIO精心挑选的地方文件系统。现有一个这样的文件系统:petardfs文章),我不知道它的开箱即用。

另一种方法是LD_PRELOAD包装器。现有的是Libfiu(用户空间中的故障注入)。它通过预加载使POSIX API调用过载的库来工作。您可以编写简单的指令或任意C代码以覆盖常规行为。


Libfiu看起来确实很有前途(并且在debian存储库中)。好的答案,谢谢,+ 1
mreithub

1

如果可以将设备文件用作“有I / O错误的文件”,则解决方案要容易得多。我的建议是针对常规文件应具有此类错误的情况。

> dd if=/dev/zero of=/path/to/ext2.img bs=10M count=10
> losetup /dev/loop0 /path/to/ext2.img
> blockdev --getsz /dev/loop0
204800
> echo "0 204800 linear /dev/loop0 0" | dmsetup create sane_dev
> mke2fs /dev/mapper/sane_dev # ext2 reicht
> mount -t ext2 /dev/mapper/sane_dev /some/where
> dd if=/dev/zero of=/some/where/unreadable_file bs=512 count=4
> hdparm --fibmap /some/where/unreadable_file
/mnt/tmp/unreadable_file:
 filesystem blocksize 1024, begins at LBA 0; assuming 512 byte sectors.
 byte_offset  begin_LBA    end_LBA    sectors
           0       2050       2053          4
> umount /dev/mapper/sane_dev
> dmsetup remove sane_dev
> start_sector=$((204800-2053-1))
> echo $'0 2053 linear /dev/loop0 0\n2053 1 error\n2054 '"${start_sector} linear /dev/loop0 2054" | 
>   dmsetup create error_dev
> mount -t ext2 /dev/mapper/error_dev /some/where
> cat /some/where/unreadable_file # 3rd sector of file is unreadable
cat: /some/where/unreadable_file: Input/output error

我必须承认我有些困惑,因为我没有设法从文件中读取单个扇区而没有错误(带有dd .. seek=...)。也许这是一个预读问题。


文件系统的块大小至少为4096字节,因此即使文件很小,它们也将跨越多个扇区。
Anon

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.