Мой вопрос в двух словах:Publishing IOMedia без основной IOBlockStorageDevice
ли это приемлемо/обычная практика для Kext опубликовать объект IOMedia, который не имеет в IOBlockStorageDevice в своих поставщиков стек?
фон:
Я пишу Kext, который будет предоставлять какое-то виртуальное устройство в пользовательское пространство. В настоящее время у меня есть драйвер, который соответствует IOResources, а затем создает объект класса, полученный из IOMedia, и прикрепляет его к «этому». После публикации этого медиа-объекта стандартный IOMediaBSDClient присоединяется к нему и создает узел в/dev /.
Первые тесты прошли хорошо, я смог успешно открыть созданное устройство и прочитать данные с него, но когда я попытался установить его с помощью родных драйверов FS, я наткнулся на проблему. Устройство было смонтировано успешно, и точка монтирования была доступна для просмотра, но через некоторое время ядро запаниковало из-за segfault, глубоко внутри кода vfs.
После долгой отладки я обнаружил, корни проблемы:
- IOMediaBSDClient реализует DKIOCGETTHROTTLEMASK IOCTL перебирая объектов IOBlockStorageDevice в СМИ родителей, а затем итерации по всем объектам СМИ, которые предоставляются этими устройствами и сочетающих их Номера BSD в битовой маске. Поскольку у моего Media нет родительских объектов IOBlockStorageDevice, полученная маска равна 0.
- Значение, возвращаемое этим ioctl, используется vfs_init_io_attributes(), чтобы заполнить поле mnt_throttle_mask структуры mp, соответствующее моему монтированию.
- Сразу после этого mnt_throttle_mask преобразуется в mnt_devbsdunit посредством вычисления в нем нужных нулей. Так как в моем случае mnt_throttle_mask равно 0, mnt_devbsdunit становится 64.
- mnt_devbsdunit используется spec_strategy (и некоторые другие функции, касающиеся дросселирование) в качестве количества элементов в _throttle_io_info, который представляет собой массив элементов LOWPRI_MAX_NUM_DEV и LOWPRI_MAX_NUM_DEV равны 64. Очевидно, что доступ к 64 элементам _throttle_io_info разбивает данные, расположенные сразу после него, что в моем случае является массивом speclisth.
На данный момент я вижу 2 пути, чтобы исправить это в моем коде: 1. Реализовать класс, производный от IOMediaBSDClient, который будет обрабатывать DKIOCGETTHROTTLEMASK IOCTL corrrectly. 2. Перепишите код, чтобы опубликовать объект IOBlockStorageDevice, и позвольте стандарту IOBlockStorageDriver опубликовать объект Media.
Лично мне нравится первое решение лучше, но проблема, с которой я столкнулась, кажется довольно хардкорной, и я не могу избавиться от мыслей, что я делаю что-то принципиально неправильное.
Я хотел бы избежать таких проблем в будущем, поэтому я задаю этот вопрос.
EDIT: это верно, по крайней мере, для OS X 10.8.3 и 10.8.5. Я еще не тестировал это в других релизах.
Спасибо за ваш ответ. Я преобразовал код в подкласс IOBlockStorageDevice, и теперь он отлично работает. В любом случае, это похоже на единственный вариант в этом случае, потому что после некоторого исследования я обнаружил, что нельзя просто переопределить DKIOCGETTHROTTLEMASK ioctl в IOMediaBSDClient, поскольку он обрабатывается непосредственно в функции dkioctl. –
Рад, что вы все разобрались! Я ранее не знал о проблеме с DKIOCGETTHROTTLEMASK, вы узнаете что-то новое каждый день. :-) – pmdj