2

現在、IOKit を使用して仮想 SCSI デバイス ドライバーを開発しています。ドライバは正常に読み込まれ、ExFat、FAT32、または HFS+ を使用してデバイスをフォーマットできます。

これらのファイル システムのいずれかで CLI を使用して、仮想デバイスとの間でファイルをコピーすることもできます。ExFat または FAT32 を使用して、Finder を使用して仮想デバイスからファイルをコピーまたは表示することもできますが、ドライブが HFS+ (ジャーナリング) でフォーマットされている場合はできません。

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 とページング (?) に関係しているため、IOMemoryDe​​scriptors を正しく処理しているかどうか疑問に思い始めています (Apple ドキュメントで読んだ内容に基づいて、正しく処理されていると思います)。誰もが同様の問題を経験していますか? これは通常、特定の種類の問題を示していますか?

更新: HFS+ でジャーナリングを無効にしても、上記の結果に影響がないことを確認しました。

UPDATE2: パニックログは毎回一貫しています。パニックは、次のすべての条件が満たされた場合にのみ発生します。

  • HFS+を使用
  • ファイルがデバイスにコピーされます (単一ファイルの場合 > 数 MB)
  • ファイルはFinderを使用してコピーされます(たとえば、端末ではありません)

最初のファイルがデバイスへのコピーを完了すると、カーネルは一貫してパニックになります。数MB以上の小さなファイルをパニックにならずにコピーできます。ターミナルを使用して大きなファイル (> 30 MB) をボリュームにコピーし、それらを Finder で読み取ったり開いたりすることもできます。

4

1 に答える 1

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()

2 マシン デバッグも役立つ場合があります。1つは、対応するvnodeがどのファイルに使用されているかを確認できますVNOP_READ。デバイスのボリューム上にないファイルでクラッシュが発生した場合は、ほぼ確実にリソースの枯渇またはメモリの破損が発生しています。ubc_create_upl()通話が失敗した正確な理由を突き止めることができます。また、コードを計測してデータを収集し、デバッガーで検査することもできます。

于 2014-07-09T08:58:43.667 に答える