Tệp đặc biệt gây ra lỗi I / O


13

Tôi muốn tự động kiểm tra nếu một phần mềm phản ứng như mong đợi nếu một tệp SQLite DB thiết yếu không được đọc (gây ra lỗi I / O). Chính xác điều đó đã xảy ra vài ngày trước tại một khách hàng. Chúng tôi đã tự sửa nó nhưng bây giờ tôi muốn tạo mã tự động để sửa nó và cần truy cập vào một tệp bị hỏng để kiểm tra điều đó.

Vì mọi thứ trong Unix là một tệp, tôi nghi ngờ rằng có thể có một tệp đặc biệt luôn gây ra lỗi I / O khi một người cố đọc nó (ví dụ: in / dev).

Một số tệp tương tự (imo) sẽ là:

  • /dev/full luôn luôn nói "Không còn chỗ trống trên thiết bị" nếu bạn cố gắng viết nó
  • /dev/null/dev/zero

Vì vậy, tôi cho rằng chỉ cần có một tệp như vậy (nhưng chưa tìm thấy tệp nào).

Có ai biết một tệp như vậy hoặc bất kỳ phương pháp nào khác để tôi nhận được kết quả mong muốn (hình ảnh phân vùng bị lỗi cố ý, trình bao bọc xung quanh open () bằng LD_PRELOAD, ...) không?
Cách tốt nhất để đi đến đây là gì?


Theo tôi biết, không có tệp đặc biệt nào trên Linux cung cấp cho SIGIO khi bạn đọc từ nó. Lần cuối cùng tôi có SIGIO là do một thanh USB tuyên bố dung lượng lớn hơn nhiều so với thực tế, vật lý. Có lẽ đó có thể là một khả năng?
lgeorget

hmmm, tôi có thể thử nó với một hình ảnh phân vùng nhỏ mà tôi sẽ cắt ở đâu đó ở giữa ...
mreithub

SIGIO không có nghĩa là đã xảy ra lỗi, đó là cách mà một chương trình có thể yêu cầu được thông báo rằng không chặn IO bây giờ là có thể, thay vì gọi select () hoặc poll ().
psusi

Up, vâng, bạn đúng, tất nhiên. Tôi đã viết SIGIO nhưng đã nghĩ về mã lỗi EIO. Nhưng có lẽ OP cũng vậy? Tại sao một thất bại để đọc cho một SIGIO?
lgeorget

ồ, tôi đã mắc lỗi tương tự trong câu hỏi ... Đã chỉnh sửa nó ...
mreithub

Câu trả lời:


8

Bạn có thể sử dụng dmsetupđể tạo ra một thiết bị ánh xạ thiết bị sử dụng một trong hai errorhoặc flakeymục tiêu để thất bại mô phỏng.

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

Trong đó 123 là chiều dài của thiết bị, trong các cung và / dev / loop0 là thiết bị gốc mà bạn muốn mô phỏng lỗi. Đối với lỗi, bạn không cần các đối số tiếp theo vì nó luôn trả về lỗi.


1
Tôi tìm thấy ít nhất hai lỗi trong lệnh đó: Tên thiết bị bị thiếu, lỗi đánh máy và "1 0 / dev / null" nghĩa là gì?
Hauke ​​Laging

@HaukeLaging, ahh, vâng, tôi đã bỏ tên và bằng cách nào đó nhấn sai. 1 0 / dev / null có nghĩa là 1 mục tiêu, bắt đầu từ offset 0, được hỗ trợ bởi thiết bị / dev / null. Nó là cần thiết cho flakey, nhưng rõ ràng là tùy chọn cho lỗi.
psusi

Dường như với tôi rằng nó không phải là "tùy chọn" mà chỉ đơn giản là bị bỏ qua. Bạn có thể kiểm tra với dmsetup table test. Bạn thậm chí có thể viết foo barphía sau error; nó chỉ không quan tâm (và do đó nên được xóa).
Hauke ​​Laging

@HaukeLaging, chỉnh sửa.
psusi

Cảm ơn câu trả lời, tôi nghĩ đó là cách tôi sẽ đi bây giờ. Vấn đề nhỏ duy nhất tôi gặp phải với vấn đề này là nó yêu cầu quyền truy cập root, nhưng tôi đoán bạn sẽ cần điều đó dù sao hay những thứ cấp thấp như vậy ... (Tôi sẽ đi sâu vào ý tưởng LD_PRELOAD khi tôi có thời gian).
mreithub

14

Đã có một bộ câu trả lời tuyệt vời cho vấn đề này trên Stack Overflow và Server Fault nhưng một số kỹ thuật đã bị thiếu. Để làm cho cuộc sống dễ dàng hơn, đây là danh sách các thiết bị chặn VM / Linux / hệ thống tập tin Linux / thư viện không gian người dùng Linux:

Phần thưởng thực tế: SQLite có trình điều khiển VFS để mô phỏng lỗi để nó có thể có được phạm vi kiểm tra tốt.

Liên quan:


5

Bạn muốn một cơ chế tiêm lỗi cho I / O.

Trên Linux, đây là một phương pháp không yêu cầu bất kỳ thiết lập nào trước đó và tạo ra một lỗi bất thường (không phải lỗi đầu vào / đầu ra EIO, nhưng ESRCH không có quy trình như vậy):

cat /proc/1234/mem

Trong đó 1234 là PID của một tiến trình đang chạy cùng một người dùng với quá trình bạn đang kiểm tra, nhưng không phải là quá trình đó. Tín dụng cho rubasov cho suy nghĩ của /proc/$pid/mem.

Nếu bạn sử dụng PID của chính quá trình, bạn sẽ nhận được EIO, nhưng chỉ khi bạn đọc từ một khu vực không được ánh xạ trong bộ nhớ của quy trình. Trang đầu tiên không bao giờ được ánh xạ, vì vậy sẽ ổn nếu bạn đọc tệp tuần tự, nhưng không phù hợp với quy trình cơ sở dữ liệu tìm kiếm trực tiếp ở giữa tệp.

Với một số thiết lập khác với quyền root, bạn có thể tận dụng trình ánh xạ thiết bị để tạo các tệp có các thành phần hợp lệ và các thành phần xấu.

Một cách tiếp cận khác là triển khai một hệ thống tập tin FUSE nhỏ . EIO là mã lỗi mặc định khi trình điều khiển hệ thống tập tin người dùng của bạn làm điều gì đó sai, vì vậy thật dễ dàng để đạt được. Cả hai liên kết PerlPython đều có các ví dụ để bắt đầu, bạn có thể nhanh chóng viết một hệ thống tệp chủ yếu phản ánh các tệp hiện có nhưng tiêm EIO vào các vị trí được chọn cẩn thận. Hiện có một hệ thống tập tin như vậy: petardfs ( bài viết ), tôi không biết nó hoạt động tốt như thế nào.

Một phương pháp khác là một LD_PRELOADtrình bao bọc. Một cái hiện có là Libfiu (lỗi tiêm trong không gian người dùng). Nó hoạt động bằng cách tải trước một thư viện làm quá tải các lệnh gọi API POSIX. Bạn có thể viết các lệnh đơn giản hoặc mã C tùy ý để ghi đè hành vi thông thường.


Libfiu trông thực sự hứa hẹn (và đó là trong repos debian). Câu trả lời tuyệt vời, cảm ơn, +1
mreithub

1

Giải pháp dễ dàng hơn rất nhiều nếu sử dụng tệp thiết bị dưới dạng "tệp có lỗi I / O". Đề xuất của tôi là cho những trường hợp một tập tin thông thường sẽ có lỗi như vậy.

> 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

Tôi phải thừa nhận rằng tôi hơi bối rối vì tôi đã không thể đọc được các cung từ các tệp đó mà không có lỗi (với dd .. seek=...). Có lẽ đó là một vấn đề đọc trước.


Các khối của hệ thống tệp của bạn có kích thước tối thiểu 4096 byte để chúng sẽ trải rộng trên nhiều lĩnh vực ngay cả khi tệp nhỏ.
Anon

1

Bạn có thể sử dụng CharybdeFS được làm chính xác cho mục đích này.

Đó là một hệ thống tập tin cầu chì thông qua như PetardFS nhưng cấu hình nhiều hơn.

Xem sách dạy nấu ăn CharybdeFS tại đây: http://www.scylladb.com/2016/05/02/fault-injection-filesystem-cookbook/

Nó đủ tiên tiến để kiểm tra cơ sở dữ liệu.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.