ไฟล์พิเศษที่ทำให้เกิดข้อผิดพลาด I / O


13

ฉันต้องการทดสอบโดยอัตโนมัติว่ามีซอฟต์แวร์ใดตอบสนองตามที่คาดหวังหากไฟล์ SQLite DB ที่สำคัญไม่สามารถอ่านได้ (ทำให้เกิดข้อผิดพลาด I / O) ตรงที่เกิดขึ้นเมื่อหลายวันก่อนที่ลูกค้า เราแก้ไขด้วยตนเอง แต่ตอนนี้ฉันต้องการสร้างรหัสอัตโนมัติเพื่อแก้ไขและต้องการเข้าถึงไฟล์ที่เสียหายเพื่อทดสอบ

ทุกอย่างในไฟล์ของ Unix ฉันสงสัยว่าอาจมีไฟล์พิเศษที่ทำให้เกิดข้อผิดพลาด I / O เมื่อพยายามอ่านไฟล์ (เช่นใน / dev)

บางไฟล์ที่คล้ายกัน (imo) จะเป็น:

  • /dev/full ซึ่งมักจะพูดว่า "ไม่มีพื้นที่เหลือบนอุปกรณ์" หากคุณพยายามเขียน
  • /dev/null และ /dev/zero

ดังนั้นฉันคิดว่าจะต้องมีไฟล์แบบนั้น (แต่ยังไม่พบ)

ไม่มีใครรู้ว่าไฟล์ดังกล่าวหรือวิธีการอื่น ๆ สำหรับฉันที่จะได้รับผลลัพธ์ที่ต้องการ (ภาพพาร์ทิชันที่ผิดพลาดโดยเจตนา, เสื้อคลุมรอบเปิด () โดยใช้ LD_PRELOAD, ... )?
วิธีที่ดีที่สุดที่จะไปที่นี่คืออะไร?


เท่าที่ฉันรู้ไม่มีไฟล์พิเศษบน Linux ที่ให้ SIGIO เมื่อคุณอ่านจากมัน ครั้งสุดท้ายที่ฉันได้รับ SIGIO นั้นเป็นเพราะแท่ง USB ที่ประกาศความจุที่ใหญ่กว่าของจริงที่มีอยู่จริง บางทีนั่นอาจเป็นความเป็นไปได้?
lgeorget

อืมฉันอาจลองกับพาร์ติชั่นอิมเมจขนาดเล็กที่ฉันจะครอบตัดตรงกลาง ...
mreithub

SIGIO ไม่ได้หมายความว่ามีข้อผิดพลาดเป็นวิธีที่โปรแกรมสามารถร้องขอให้ได้รับการแจ้งเตือนว่าตอนนี้ไม่สามารถทำการบล็อก IO ได้แล้วแทนที่จะเรียก select () หรือ poll ()
psusi

แน่นอนคุณพูดถูก ฉันเขียน SIGIO แต่คิดว่ารหัสข้อผิดพลาด EIO แต่บางที OP ด้วยใช่ไหม ทำไมความล้มเหลวในการอ่านจึงให้ SIGIO
lgeorget

โอ้ฉันทำผิดพลาดเหมือนกันในคำถาม ... แก้ไขมัน ...
mreithub

คำตอบ:


8

คุณสามารถใช้dmsetupเพื่อสร้างอุปกรณ์อุปกรณ์ทำแผนที่โดยใช้errorหรือflakeyเป้าหมายเพื่อจำลองความล้มเหลว

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 เป้าหมายเริ่มต้นที่ offset 0 สนับสนุนโดยอุปกรณ์ / dev / null มันเป็นสิ่งจำเป็นสำหรับความไม่แน่นอน
psusi

ฉันว่ามันไม่ใช่ "ตัวเลือก" แต่ก็ไม่สนใจเลย dmsetup table testคุณอาจจะตรวจสอบกับ คุณสามารถเขียนfoo barข้างหลังerror; มันไม่สนใจ (และควรลบ)
Hauke ​​Laging

@HaukeLaging แก้ไขแล้ว
psusi

ขอบคุณสำหรับคำตอบฉันคิดว่านั่นเป็นวิธีที่ฉันจะไปตอนนี้ ปัญหาเล็กน้อยเดียวที่ฉันมีในเรื่องนี้คือต้องใช้การเข้าถึงรูท แต่ฉันคิดว่าคุณจะต้องการสิ่งนั้นหรือสิ่งที่ต่ำกว่าระดับนั้น ... (ฉันจะขุดลงในแนวคิด LD_PRELOAD เมื่อฉันมีเวลา)
mreithub

14

มีชุดของคำตอบที่ดีเกี่ยวกับ Stack Overflow และ Server Fault แล้ว แต่เทคนิคบางอย่างขาดหายไป เพื่อทำให้ชีวิตง่ายขึ้นนี่คือรายการของอุปกรณ์บล็อก VM / Linux / ระบบไฟล์ Linux / Linux userspace library I / O กลไกการฉีดข้อบกพร่อง:

ความเป็นจริงของโบนัส: SQLite มีไดรเวอร์ VFS สำหรับการจำลองข้อผิดพลาดเพื่อให้สามารถครอบคลุมการทดสอบได้ดี

ที่เกี่ยวข้อง:


5

คุณต้องการกลไกการฉีดผิดสำหรับ I / O

บน Linux นี่คือวิธีการที่ไม่ต้องใช้การตั้งค่าก่อนหน้าและสร้างข้อผิดพลาดที่ผิดปกติ (ไม่ใช่ EIO“ ข้อผิดพลาดอินพุต / เอาต์พุต” แต่ ESRCH“ ไม่มีกระบวนการดังกล่าว”):

cat /proc/1234/mem

โดยที่ 1234 เป็น PID ของกระบวนการที่ทำงานในฐานะผู้ใช้เดียวกับกระบวนการที่คุณกำลังทดสอบ แต่ไม่ใช่กระบวนการนั้น เครดิตrubasovสำหรับความคิด/proc/$pid/memของ

หากคุณใช้ PID ของกระบวนการคุณจะได้รับ EIO แต่ถ้าคุณกำลังอ่านจากพื้นที่ที่ไม่ได้ถูกแมปในหน่วยความจำของกระบวนการ หน้าแรกไม่เคยถูกแมปดังนั้นจึงเป็นเรื่องปกติถ้าคุณอ่านไฟล์ตามลำดับ แต่ไม่เหมาะสำหรับกระบวนการฐานข้อมูลที่ค้นหาตรงกลางไฟล์

ด้วยการตั้งค่าเพิ่มเติมบางอย่างในฐานะรูทคุณสามารถใช้ประโยชน์จาก mapper อุปกรณ์เพื่อสร้างไฟล์ที่มีเซกเตอร์ที่ถูกต้องและเซกเตอร์เสีย

อีกวิธีคือการใช้ระบบไฟล์FUSEขนาดเล็ก EIO เป็นรหัสข้อผิดพลาดเริ่มต้นเมื่อไดรเวอร์ระบบไฟล์ userspace ของคุณทำอะไรผิดพลาดดังนั้นจึงง่ายต่อการบรรลุผล ทั้งการผูกPerlและPythonมาพร้อมกับตัวอย่างเพื่อเริ่มต้นคุณสามารถเขียนระบบไฟล์ที่ทำมิเรอร์ไฟล์ที่มีอยู่เป็นส่วนใหญ่ได้อย่างรวดเร็ว แต่อัดฉีด EIO ในสถานที่ที่เลือกอย่างระมัดระวัง มีระบบไฟล์ดังกล่าวอยู่แล้ว: petardfs ( บทความ ) ฉันไม่รู้ว่ามันใช้งานได้ดีแค่ไหน

อีกวิธีคือLD_PRELOADเสื้อคลุม อันที่มีอยู่คือLibfiu (การฉีดข้อผิดพลาดใน userspace) มันทำงานได้โดยการโหลดห้องสมุดที่โหลด POSIX API มากเกินไป คุณสามารถเขียนคำสั่งอย่างง่ายหรือรหัส C โดยพลการเพื่อแทนที่พฤติกรรมปกติ


Libfiu ดูมีความหวังดีมาก (และอยู่ใน debos repos) คำตอบที่ดีขอบคุณ +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

1

คุณสามารถใช้ CharybdeFS ที่ทำขึ้นเพื่อจุดประสงค์ประเภทนี้อย่างแน่นอน

มันเป็นระบบไฟล์ passthrough ฟิวส์เช่น PetardFS แต่สามารถกำหนดค่าได้มากกว่า

ดูตำรา CharybdeFS ที่นี่: http://www.scylladb.com/2016/05/02/fault-injection-filesystem-cookbook/

มันสูงพอที่จะทดสอบฐานข้อมูล


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.