Драйвер виртуального дискового устройства SCSI в OS X вызывает панику, когда устройство отформатировано с использованием только HFS+

В настоящее время я разрабатываю драйвер виртуального устройства SCSI с использованием IOKit. Мой драйвер загружается нормально, и я могу отформатировать свое устройство, используя ExFat, FAT32 или HFS+.

Я также могу копировать файлы на виртуальное устройство и с него, используя интерфейс командной строки с любой из этих файловых систем. Используя ExFat или FAT32, я также могу копировать или просматривать файлы с моего виртуального устройства с помощью Finder, но не тогда, когда диск отформатирован в HFS+ (Journaled).

При использовании HFS + я получаю панику ядра, связанную с Finder, Spotlight или Preview. Это происходит, например, когда система пытается просмотреть файл после того, как он был скопирован на диск. Вот пример журнала от паники ядра:

Mon Jun 30 22:47:51 2014
panic(cpu 4 caller 0xffffff8005dd1401): "cluster_read_copy: failed to get pagelist"@/SourceCache/xnu/xnu-2422.100.13/bsd/vfs/vfs_cluster.c:3732
Backtrace (CPU 4), Frame : Return Address
0xffffff80e9aa3810 : 0xffffff8005c22fa9
0xffffff80e9aa3890 : 0xffffff8005dd1401
0xffffff80e9aa3a30 : 0xffffff8005dd0a85
0xffffff80e9aa3cf0 : 0xffffff8005f6b876
0xffffff80e9aa3d80 : 0xffffff8005dfdd21
0xffffff80e9aa3e00 : 0xffffff8005df38d5
0xffffff80e9aa3e50 : 0xffffff8005ff1cfe
0xffffff80e9aa3ef0 : 0xffffff8005ff1e79
0xffffff80e9aa3f50 : 0xffffff8006040653
0xffffff80e9aa3fb0 : 0xffffff8005cf3c56

BSD process name corresponding to current thread: Finder
Boot args: debug=0x144

Mac OS version:
13D65

Kernel version:
Darwin Kernel Version 13.2.0: Thu Apr 17 23:03:13 PDT 2014; root:xnu-2422.100.13~1/RELEASE_X86_64

Вот трассировка стека для вышеуказанного журнала паники:

mach_kernel`panic + 201 at debug.c:353
mach_kernel`cluster_read_copy + 2001 at vfs_cluster.c:3732
mach_kernel`cluster_read_ext + 5045 at vfs_cluster.c:3441
mach_kernel`hfs_vnop_read + 566 at hfs_readwrite.c
mach_kernel`VNOP_READ + 225 at kpi_vfs.c:3247
mach_kernel`vn_read + 245 at vfs_vnops.c:939
mach_kernel`dofileread + 174 at sys_generic.c:377
mach_kernel`pread_nocancel + 137 at sys_generic.c:266
mach_kernel`unix_syscall64 + 499 at systemcalls.c:370
mach_kernel`hndl_unix_scall64 + 22

У меня были трудности с определением проблемы, но, как указано выше, сузился до HFS+. Есть ли что-то особенное в HFS +, которое может вызвать это?

Так как проблема связана с VFS и подкачкой страниц (?), Я начинаю задумываться, правильно ли я обрабатываю свои IOMemoryDescriptors (я так думаю, основываясь на том, что я прочитал в документации Apple). Кто-нибудь испытывает подобные проблемы? Это обычно указывает на конкретный тип проблемы?

ОБНОВЛЕНИЕ: я убедился, что отключение ведения журнала в HFS + не влияет на вышеуказанные результаты.

ОБНОВЛЕНИЕ 2: журналы паники согласованы каждый раз. Паника возникает только при выполнении ВСЕХ следующих условий:

  • HFS + используется
  • Файл копируется на устройство (для одного файла> несколько МБ)
  • Файл копируется с помощью Finder (но не терминала, например)

Ядро постоянно впадает в панику, когда первый файл заканчивает копирование на устройство. Многие небольшие файлы размером не более нескольких МБ могут быть скопированы без паники. Я даже могу копировать файлы больших файлов (> 30 МБ) на том с помощью терминала и читать / открывать их в Finder.

1 ответ

Источник в ядре предполагает, что паника вызвана ошибочным вызовом ubc_create_upl(), Комментарии в источнике для этой функции в свою очередь предполагают, что режимы возврата следующие:

 * Returns: KERN_SUCCESS        The requested upl has been created
 *      KERN_INVALID_ARGUMENT   The bufsize argument is not an even
 *                  multiple of the page size
 *      KERN_INVALID_ARGUMENT   There is no ubc_info associated with
 *                  the vnode, or there is no memory object
 *                  control associated with the ubc_info 
 *  memory_object_upl_request:KERN_INVALID_VALUE
 *                  The supplied upl_flags argument is
 *                  invalid

Исходя из разборки и содержимого реестра вашего журнала паники (который вы не указали в вопросе), можно определить действительный код возврата. Не то чтобы это выглядело так, как будто это сильно поможет, так как ваш код еще не был вызван для этого конкретного системного вызова; Я сильно подозреваю, что вы заставляете некоторый ресурс ядра истощаться, и это как раз тот момент, когда пул какого-то вида полностью иссякает. Вполне возможно, дескрипторы памяти, как вы говорите, поскольку созданный здесь UPL будет помещен в дескриптор памяти и затем передан в бэкэнд IOKit блочного устройства монтирования.

Вы можете проверить ioclasscount и возможно zprint прежде чем загружать драйвер, а затем периодически сбрасывать их вывод снова до сбоя, а затем сравнивать выводы для всего, что убегает. Также хорошей идеей будет проверка вашего кода на соответствие prepare()/complete() а также retain()/release() звонки, особенно по дескрипторам памяти запросов.

Отладка с двумя машинами тоже может помочь; для одного вы можете проверить, какой файл vnode используется для VNOP_READ соответствует. Если происходит сбой файла, который отсутствует даже на томе вашего устройства, то вы почти наверняка испытали некоторое истощение ресурсов или повреждение памяти. Вы сможете найти точную причину ubc_create_upl() вызов не выполняется. Кроме того, вы можете использовать свой код для сбора данных, которые затем сможете проверить в отладчике.

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