Драйвер блочного устройства - Понимание полученного ioctl

Я только что реализовал виртуальное блочное устройство, и во время игры с ним я увидел странное поведение, связанное с ioctls.

Мое устройство - это просто зона памяти, разделенная на два сектора по 512 байт. В настоящее время я могу читать / писать из / в него с определенным смещением, используя системные вызовы.

Устройство также защищено от одновременного доступа к записи. Он принимает неограниченное количество читателей, но только один писатель за раз, и только если в настоящее время никто не читает из него.

Ioctl еще не обработан, но, несмотря на это, я записывал соответствующую информацию.

int block_mod_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
    DEBUG("Entering IOCTL handling function\n");
    switch(cmd)
    {
        default:
            WARNING("Unknown ioctl call: %x\n", cmd);
            WARNING("Ioctl: type=%x\tnumber=%x\tdirection=%x\tsize=%x\n", _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_DIR(cmd), _IOC_SIZE(cmd));
            return -1;
    }
    return 0;
}

Я играл с dd и я обнаружил странное поведение, которое я не понимаю после некоторого рытья вокруг.

# dd if=/dev/blkmodtest of=file.out seek=10
[  107.367797] Oppened in read only mode
[  107.368595] Read access: 1   Write access: 0
[  107.370367] Reading from device
[  107.372939] Closed read only mode
[  107.373690] Read access: 0   Write access: 0
2+0 records in
2+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.00584625 s, 175 kB/s

# dd if=/dev/blkmodtest of=file.out skip=10
[  111.982493] Oppened in read only mode
[  111.983326] Read access: 1   Write access: 0
[  111.985247] Unknown ioctl call: 80306d02
[  111.986096] Ioctl: type=6d   number=2    direction=2 size=30
[  111.987618] Unknown ioctl call: 80306d02
[  111.988436] Ioctl: type=6d   number=2    direction=2 size=30
dd: /dev/blkmodtest: cannot skip: Invalid argument
[  111.991032] Closed read only mode
[  111.991705] Read access: 0   Write access: 0
0+0 records in
0+0 records out
0 bytes copied, 0.00783969 s, 0.0 kB/s

Кажется, что dd выполняет вызов ioctl, который мой драйвер не может (очевидно) обработать. Я знаю что не должен давать skip=10 но seek=10 как я читаю с устройства, но это было для целей тестирования.

Я в настоящее время пытаюсь понять, почему этот ioctl выпущен и с какой целью?

Если я хорошо понимаю документацию, которую я нашел, тип ioctl 'm' который должен быть описан в одном из следующих файлов ( источник):

'm' 00-09   linux/mmtimer.h     conflict!
'm' all linux/mtio.h        conflict!
'm' all linux/soundcard.h   conflict!
'm' all linux/synclink.h    conflict!
'm' 00-19   drivers/message/fusion/mptctl.h conflict!
'm' 00 drivers/scsi/megaraid/megaraid_ioctl.h conflict!

Я проверил эти файлы, но не могу найти полезную информацию, которая поможет мне понять, что происходит в этом конкретном случае.

1 ответ

Решение

Настройка петлевого устройства (sudo losetup loop0 /path/to/some/image), выход strace dd if=/dev/loop0 of=out.data skip=10 bs=40 count=2 содержит

open("/dev/loop0", O_RDONLY)            = 3
dup2(3, 0)                              = 0
close(3)                                = 0
lseek(0, 0, SEEK_CUR)                   = 0
ioctl(0, MTIOCGET, 0x7fffac670080)      = -1 EINVAL (Invalid argument)
lseek(0, 400, SEEK_CUR)                 = 400
fstat(0, {st_mode=S_IFBLK|0660, st_rdev=makedev(7, 0), ...}) = 0

что указывает dd пытается сделать MTIOCGET ioctl на вашем блочном устройстве. man 4 st шоу

Драйвер st обеспечивает интерфейс для различных ленточных устройств SCSI.
[...]
MTIOCGET - получить статус
Этот запрос принимает аргумент типа (struct mtget *).

Другими словами, dd подозревает, что ваше блочное устройство может быть ленточным устройством SCSI, и запрашивает его состояние, используя ioctl() вы видите

Ваш водитель может вернуться EINVAL за это; это то, что делают, например, петлевые устройства.

Другие вопросы по тегам