Как восстановить ошибку ввода-вывода базового блочного устройства - PullRequest
0 голосов
/ 09 января 2019

Рассмотрим устройство в системе, что-то в / dev / hdd [sg] [nvme] xx Откройте устройство, получите дескриптор файла и начните работать с ним (read(v) / write(v) / lseek и т. Д.), В какой-то момент вы можете получить EIO. Как получить исходную ошибку, сообщенную драйвером устройства?

EDIT001: если невозможно использовать функции unistd, возможно, есть другие способы работы с блочными устройствами, которые могут предоставлять более низкоуровневую информацию, такую ​​как sg_scsi_sense_hdr?

1 Ответ

0 голосов
/ 10 января 2019

Вы не можете получить более подробную информацию об ошибках из функций POSIX. Вы на правильном пути с универсальным материалом SCSI. Но, мальчик, он загружен волосами. Посмотрите в sg3_utils пример того, как выполнить чтение SCSI (16). Это позволит вам посмотреть на сенсорные данные, когда они вернутся:

https://github.com/hreinecke/sg3_utils/blob/master/examples/sg_simple16.c

Конечно, этот метод не работает с накопителями NVMe. (По крайней мере, насколько мне известно).

Одна из концепций, с которыми я играл в прошлом, заключается в использовании обычных функций ввода / вывода для блоков POSIX / libc, таких как pread и pwrite, до тех пор, пока я не выведу EIO. В этот момент вы можете ввести универсальные версии SCSI, чтобы попытаться выяснить, что произошло. В идеальном случае pread или lseek/read завершается неудачно с EIO. Затем вы поворачиваетесь и переиздаете его, используя СЧИТЫВАНИЕ SG (10) или (16). Если это не просто временный сбой, это может вернуть данные о состоянии, которые может использовать ваше приложение.

Вот пример использования программы sg_read из командной строки. У меня есть диск iSCSI, который я читаю и пишу. На цели я удаляю его сопоставление LUN. dd сообщает EIO:

# dd if=/dev/sdb of=/tmp/output bs=512 count=1 iflag=direct
dd: error reading ‘/dev/sdb’: Input/output error

но sg_read сообщает еще немного полезной информации:

[root@localhost src]# sg_read blk_sgio=1 bs=512 cdbsz=10 count=512 if=/dev/sdb odir=1 verbose=10
Opened /dev/sdb for SG_IO with flags=0x4002
    read cdb: 28 00 00 00 00 00 00 00 80 00
      duration=9 ms
reading: SCSI status: Check Condition
 Fixed format, current;  Sense key: Illegal Request
 Additional sense: Logical unit not supported
 Raw sense data (in hex):
        70 00 05 00 00 00 00 0a  00 00 00 00 25 00 00 00
        00 00
sg_read: SCSI READ failed
Some error occurred,  remaining block count=512
0+0 records in

Вы можете увидеть дополнительный смысловой код Logical unit not supported в вышеприведенном выводе, указывающий, что в цели нет такого LU.

возможно? Да. Но, как видно из кода в sg_simple16.c, это не просто!

...