<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="https://openzfsonosx.org/w/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://openzfsonosx.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=92.225.159.249</id>
		<title>OpenZFS on OS X - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://openzfsonosx.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=92.225.159.249"/>
		<link rel="alternate" type="text/html" href="https://openzfsonosx.org/wiki/Special:Contributions/92.225.159.249"/>
		<updated>2026-05-09T21:14:46Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.22.3</generator>

	<entry>
		<id>https://openzfsonosx.org/wiki/Development</id>
		<title>Development</title>
		<link rel="alternate" type="text/html" href="https://openzfsonosx.org/wiki/Development"/>
				<updated>2014-06-02T22:49:34Z</updated>
		
		<summary type="html">&lt;p&gt;92.225.159.249: /* File-based zpools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:O3X development]]&lt;br /&gt;
You should also familiarize yourself with the [[Project_roadmap|project roadmap]] so that you can put the technical details here in context.&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
&lt;br /&gt;
=== Debugging with GDB ===&lt;br /&gt;
&lt;br /&gt;
Dealing with [[Panic|panics]].&lt;br /&gt;
&lt;br /&gt;
Apple's documentation: https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptDebugger/debug_tutorial.html&lt;br /&gt;
&lt;br /&gt;
Boot target VM with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo nvram boot-args=&amp;quot;-v keepsyms=y debug=0x144&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make it panic.&lt;br /&gt;
&lt;br /&gt;
On your development machine, you will need the Kernel Debug Kit. Download it from Apple [https://developer.apple.com/downloads/index.action?q=Kernel%20Debug%20Kit here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
$ gdb /Volumes/Kernelit/mach_kernel&lt;br /&gt;
(gdb) source /Volumes/KernelDebugKit/kgmacros&lt;br /&gt;
(gdb) target remote-kdp&lt;br /&gt;
(gdb) kdp-reattach  192.168.30.133   # obviously use the IP of your target / crashed VM&lt;br /&gt;
(gdb) showallkmods&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Find the addresses for ZFS and SPL modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;^Z&amp;lt;/code&amp;gt; to suspend gdb, or, use another terminal&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
^Z&lt;br /&gt;
$ sudo kextutil -s /tmp -n \&lt;br /&gt;
-k /Volumes/KernelDebugKit/mach_kernel \&lt;br /&gt;
-e -r /Volumes/KernelDebugKit module/zfs/zfs.kext/ \&lt;br /&gt;
../spl/module/spl/spl.kext/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then resume gdb, or go back to gdb terminal.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
$ fg&lt;br /&gt;
(gdb) set kext-symbol-file-path /tmp&lt;br /&gt;
(gdb) add-kext /tmp/spl.kext &lt;br /&gt;
(gdb) add-kext /tmp/zfs.kext&lt;br /&gt;
(gdb) bt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debugging with LLDB ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo &amp;quot;settings set target.load-script-from-symbol-file true&amp;quot; &amp;gt;&amp;gt; ~/.lldbinit&lt;br /&gt;
$ lldb /Volumes/KernelDebugKit/mach_kernel&lt;br /&gt;
(lldb) kdp-remote  192.168.30.146&lt;br /&gt;
(lldb) showallkmods&lt;br /&gt;
(lldb) addkext -F /tmp/spl.kext/Contents/MacOS/spl 0xffffff7f8ebb0000   (Address from showallkmods)&lt;br /&gt;
(lldb) addkext -F /tmp/zfs.kext/Contents/MacOS/zfs 0xffffff7f8ebbf000&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then follow the guide for GDB above.&lt;br /&gt;
&lt;br /&gt;
=== Non-panic ===&lt;br /&gt;
&lt;br /&gt;
If you prefer to work in GDB, you can always panic a kernel with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo dtrace -w -n &amp;quot;BEGIN{ panic();}&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But this was revealing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo /usr/libexec/stackshot -i -f /tmp/stackshot.log &lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -w /tmp/trace.txt&lt;br /&gt;
$ less /tmp/trace.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that my hang is here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
PID: 156&lt;br /&gt;
    Process: zpool&lt;br /&gt;
    Thread ID: 0x4e2&lt;br /&gt;
    Thread state: 0x9 == TH_WAIT |TH_UNINT &lt;br /&gt;
    Thread wait_event: 0xffffff8006608a6c&lt;br /&gt;
    Kernel stack: &lt;br /&gt;
    machine_switch_context (in mach_kernel) + 366 (0xffffff80002b3d3e)&lt;br /&gt;
      0xffffff800022e711 (in mach_kernel) + 1281 (0xffffff800022e711)&lt;br /&gt;
        thread_block_reason (in mach_kernel) + 300 (0xffffff800022d9dc)&lt;br /&gt;
          lck_mtx_sleep (in mach_kernel) + 78 (0xffffff80002265ce)&lt;br /&gt;
            0xffffff8000569ef6 (in mach_kernel) + 246 (0xffffff8000569ef6)&lt;br /&gt;
              msleep (in mach_kernel) + 116 (0xffffff800056a2e4)&lt;br /&gt;
                0xffffff7f80e52a76 (0xffffff7f80e52a76)&lt;br /&gt;
                  0xffffff7f80e53fae (0xffffff7f80e53fae)&lt;br /&gt;
                    0xffffff7f80e54173 (0xffffff7f80e54173)&lt;br /&gt;
                      0xffffff7f80f1a870 (0xffffff7f80f1a870)&lt;br /&gt;
                        0xffffff7f80f2bb4e (0xffffff7f80f2bb4e)&lt;br /&gt;
                          0xffffff7f80f1a9b7 (0xffffff7f80f1a9b7)&lt;br /&gt;
                            0xffffff7f80f1b65f (0xffffff7f80f1b65f)&lt;br /&gt;
                              0xffffff7f80f042ee (0xffffff7f80f042ee)&lt;br /&gt;
                                0xffffff7f80f45c5b (0xffffff7f80f45c5b)&lt;br /&gt;
                                  0xffffff7f80f4ce92 (0xffffff7f80f4ce92)&lt;br /&gt;
                                    spec_ioctl (in mach_kernel) + 157 (0xffffff8000320bfd)&lt;br /&gt;
                                      VNOP_IOCTL (in mach_kernel) + 244 (0xffffff8000311e84)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a shame that it only shows the kernel symbols, and not inside SPL and ZFS, but we can ask it to load another sym file. (Alas, it cannot handle multiple symbols files. Fix this Apple.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo kextstat #grab the addresses of SPL and ZFS again&lt;br /&gt;
$ sudo kextutil -s /tmp -n -k /Volumes/KernelDebugKit/mach_kernel \&lt;br /&gt;
-e -r /Volumes/KernelDebugKit module/zfs/zfs.kext/ ../spl/module/spl/spl.kext/ &lt;br /&gt;
&lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -k /tmp/net.lundman.spl.sym&lt;br /&gt;
              0xffffff800056a2e4 (0xffffff800056a2e4)&lt;br /&gt;
                spl_cv_wait (in net.lundman.spl.sym) + 54 (0xffffff7f80e52a76)&lt;br /&gt;
                  taskq_wait (in net.lundman.spl.sym) + 78 (0xffffff7f80e53fae)&lt;br /&gt;
                    taskq_destroy (in net.lundman.spl.sym) + 35 (0xffffff7f80e54173)&lt;br /&gt;
                      0xffffff7f80f1a870 (0xffffff7f80f1a870)&lt;br /&gt;
&lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -k /tmp/net.lundman.zfs.sym&lt;br /&gt;
                    0xffffff7f80e54173 (0xffffff7f80e54173)&lt;br /&gt;
                      vdev_open_children (in net.lundman.zfs.sym) + 336 (0xffffff7f80f1a870)&lt;br /&gt;
                        vdev_root_open (in net.lundman.zfs.sym) + 94 (0xffffff7f80f2bb4e)&lt;br /&gt;
                          vdev_open (in net.lundman.zfs.sym) + 311 (0xffffff7f80f1a9b7)&lt;br /&gt;
                            vdev_create (in net.lundman.zfs.sym) + 31 (0xffffff7f80f1b65f)&lt;br /&gt;
                              spa_create (in net.lundman.zfs.sym) + 878 (0xffffff7f80f042ee)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voilà!&lt;br /&gt;
&lt;br /&gt;
=== Memory leaks ===&lt;br /&gt;
&lt;br /&gt;
In some cases, you may suspect memory issues, for instance if you saw the following panic:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
panic(cpu 1 caller 0xffffff80002438d8): &amp;quot;zalloc: \&amp;quot;kalloc.1024\&amp;quot; (100535 elements) retry fail 3, kfree_nop_count: 0&amp;quot;@/SourceCache/xnu/xnu-2050.7.9/osfmk/kern/zalloc.c:1826&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To debug this, you can attach GDB and use the zprint command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) zprint&lt;br /&gt;
ZONE                   COUNT   TOT_SZ   MAX_SZ   ELT_SZ ALLOC_SZ         TOT_ALLOC         TOT_FREE NAME&lt;br /&gt;
0xffffff8002a89250   1620133  18c1000  22a3599       16     1000         125203838        123583705 kalloc.16 CX&lt;br /&gt;
0xffffff8006306c50    110335   35f000   4ce300       32     1000          13634985         13524650 kalloc.32 CX&lt;br /&gt;
0xffffff8006306a00    133584   82a000   e6a900       64     1000          26510120         26376536 kalloc.64 CX&lt;br /&gt;
0xffffff80063067b0    610090  4a84000  614f4c0      128     1000          50524515         49914425 kalloc.128 CX&lt;br /&gt;
0xffffff8006306560   1070398 121a2000 1b5e4d60      256     1000          72534632         71464234 kalloc.256 CX&lt;br /&gt;
0xffffff8006306310    399302  d423000  daf26b0      512     1000          39231204         38831902 kalloc.512 CX&lt;br /&gt;
0xffffff80063060c0    100404  6231000  c29e980     1024     1000          22949693         22849289 kalloc.1024 CX&lt;br /&gt;
0xffffff8006305e70       292    9a000   200000     2048     1000          77633725         77633433 kalloc.2048 CX&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, kalloc.256 is suspect.&lt;br /&gt;
&lt;br /&gt;
Reboot kernel with zlog=kalloc.256 on the command line, then we can use&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) findoldest                                                                &lt;br /&gt;
oldest record is at log index 393:&lt;br /&gt;
&lt;br /&gt;
--------------- ALLOC  0xffffff803276ec00 : index 393  :  ztime 21643824 -------------&lt;br /&gt;
0xffffff800024352e &amp;lt;zalloc_canblock+78&amp;gt;:        mov    %eax,-0xcc(%rbp)&lt;br /&gt;
0xffffff80002245bd &amp;lt;get_zone_search+23&amp;gt;:        jmpq   0xffffff80002246d8 &amp;lt;KALLOC_ZINFO_SALLOC+35&amp;gt;&lt;br /&gt;
0xffffff8000224c39 &amp;lt;OSMalloc+89&amp;gt;:       mov    %rax,-0x18(%rbp)&lt;br /&gt;
0xffffff7f80e847df &amp;lt;zfs_kmem_alloc+15&amp;gt;: mov    %rax,%r15&lt;br /&gt;
0xffffff7f80e90649 &amp;lt;arc_buf_alloc+41&amp;gt;:  mov    %rax,-0x28(%rbp)&lt;br /&gt;
and indeed, list any index&lt;br /&gt;
&lt;br /&gt;
(gdb) zstack 394&lt;br /&gt;
&lt;br /&gt;
--------------- ALLOC  0xffffff8032d60700 : index 394  :  ztime 21648810 -------------&lt;br /&gt;
0xffffff800024352e &amp;lt;zalloc_canblock+78&amp;gt;:        mov    %eax,-0xcc(%rbp)&lt;br /&gt;
0xffffff80002245bd &amp;lt;get_zone_search+23&amp;gt;:        jmpq   0xffffff80002246d8 &amp;lt;KALLOC_ZINFO_SALLOC+35&amp;gt;&lt;br /&gt;
0xffffff8000224c39 &amp;lt;OSMalloc+89&amp;gt;:       mov    %rax,-0x18(%rbp)&lt;br /&gt;
0xffffff7f80e847df &amp;lt;zfs_kmem_alloc+15&amp;gt;: mov    %rax,%r15&lt;br /&gt;
0xffffff7f80e90649 &amp;lt;arc_buf_alloc+41&amp;gt;:  mov    %rax,-0x28(%rbp)&lt;br /&gt;
How many times was zfs_kmem_alloc involved in the leaked allocs?&lt;br /&gt;
&lt;br /&gt;
(gdb) countpcs 0xffffff7f80e847df&lt;br /&gt;
occurred 3999 times in log (100% of records)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At least we know it is our fault.&lt;br /&gt;
&lt;br /&gt;
How many times is it arc_buf_alloc?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) countpcs 0xffffff7f80e90649&lt;br /&gt;
occurred 2390 times in log (59% of records)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Flamegraphs ==&lt;br /&gt;
&lt;br /&gt;
Huge thanks to [http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html BrendanGregg] for so much of the dtrace magic.&lt;br /&gt;
&lt;br /&gt;
dtrace the kernel while running a command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo dtrace -x stackframes=100 -n 'profile-997 /arg0/ {&lt;br /&gt;
    @[stack()] = count(); } tick-60s { exit(0); }' -o out.stacks&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will run for 60 seconds.&lt;br /&gt;
&lt;br /&gt;
Convert it to a flamegraph:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./stackcollapse.pl out.stacks &amp;gt; out.folded&lt;br /&gt;
$ ./flamegraph.pl out.folded &amp;gt; out.svg&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is &amp;lt;code&amp;gt;rsync -a /usr/ /BOOM/deletea/&amp;lt;/code&amp;gt; running:&lt;br /&gt;
&lt;br /&gt;
[[File:rsyncflamegraph.svg|thumb|rsync flamegraph]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Or running '''Bonnie++''' in various stages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed-hover&amp;quot;&amp;gt;&lt;br /&gt;
File:create.svg|Create files in sequential order|alt=[[File:create.svg]]&lt;br /&gt;
File:stat.svg|Stat files in sequential order|alt=Stat files in sequential order&lt;br /&gt;
File:delete.svg|Delete files in sequential order|alt=Delete files in sequential order&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:VX_create.svg|thumb|Create files in sequential order]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:iozone.svg|thumb|IOzone flamegraph]]&lt;br /&gt;
&lt;br /&gt;
[[File:iozoneX.svg|thumb|IOzone flamegraph (untrimmed)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------&lt;br /&gt;
&lt;br /&gt;
== Iozone ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Quick peek at how they compare, just to see how much we should improve it by.&lt;br /&gt;
&lt;br /&gt;
HFS+ and ZFS were created on the same virtual disk in VMware. Of course, this is not ideal testing specs, but should serve as an indicator. &lt;br /&gt;
&lt;br /&gt;
The pool was created with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool create -f -o ashift=12 \&lt;br /&gt;
-O atime=off \&lt;br /&gt;
-O casesensitivity=insensitive \&lt;br /&gt;
-O normalization=formD \&lt;br /&gt;
BOOM /dev/disk1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the HFS+ file system was created with the standard OS X Disk Utility.app, with everything default (journaled, case-insensitive).&lt;br /&gt;
&lt;br /&gt;
'''Iozone''' was run with standard automode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo iozone -a -b outfile.xls&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:hfs2_read.png|thumb|HFS+ read]]&lt;br /&gt;
[[File:hfs2_write.png|thumb|HFS+ write]]&lt;br /&gt;
[[File:zfs2_read.png|thumb|ZFS read]]&lt;br /&gt;
[[File:zfs2_write.png|thumb|ZFS write]]&lt;br /&gt;
&lt;br /&gt;
As a guess, writes need to double, and reads need to triple.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== VFS ===&lt;br /&gt;
&lt;br /&gt;
[[VFS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File-based zpools for testing==&lt;br /&gt;
&lt;br /&gt;
* create 2 files (each 100 MB) to be used as block devices:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ dd if=/dev/zero bs=1m count=100 of=vdisk1&lt;br /&gt;
$ dd if=/dev/zero bs=1m count=100 of=vdisk2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* attach files as raw disk images:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount vdisk1&lt;br /&gt;
/dev/disk2&lt;br /&gt;
$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount vdisk2&lt;br /&gt;
/dev/disk3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* create mirrored zpool:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool create -f -o ashift=12 -O casesensitivity=insensitive -O normalization=formD tank mirror disk2 disk3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* show zpool:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool status&lt;br /&gt;
  pool: tank&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
  scan: none requested&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME        STATE     READ WRITE CKSUM&lt;br /&gt;
	tank        ONLINE       0     0     0&lt;br /&gt;
	  mirror-0  ONLINE       0     0     0&lt;br /&gt;
	    disk2   ONLINE       0     0     0&lt;br /&gt;
	    disk3   ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* test ZFS features, find bugs, ...&lt;br /&gt;
&lt;br /&gt;
* export zpool:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool export tank&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* detach raw images:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ hdiutil detach disk2&lt;br /&gt;
&amp;quot;disk2&amp;quot; unmounted.&lt;br /&gt;
&amp;quot;disk2&amp;quot; ejected.&lt;br /&gt;
$ hdiutil detach disk3&lt;br /&gt;
&amp;quot;disk3&amp;quot; unmounted.&lt;br /&gt;
&amp;quot;disk3&amp;quot; ejected.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>92.225.159.249</name></author>	</entry>

	<entry>
		<id>https://openzfsonosx.org/wiki/Development</id>
		<title>Development</title>
		<link rel="alternate" type="text/html" href="https://openzfsonosx.org/wiki/Development"/>
				<updated>2014-06-02T22:48:56Z</updated>
		
		<summary type="html">&lt;p&gt;92.225.159.249: /* File-based zpools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:O3X development]]&lt;br /&gt;
You should also familiarize yourself with the [[Project_roadmap|project roadmap]] so that you can put the technical details here in context.&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
&lt;br /&gt;
=== Debugging with GDB ===&lt;br /&gt;
&lt;br /&gt;
Dealing with [[Panic|panics]].&lt;br /&gt;
&lt;br /&gt;
Apple's documentation: https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptDebugger/debug_tutorial.html&lt;br /&gt;
&lt;br /&gt;
Boot target VM with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo nvram boot-args=&amp;quot;-v keepsyms=y debug=0x144&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make it panic.&lt;br /&gt;
&lt;br /&gt;
On your development machine, you will need the Kernel Debug Kit. Download it from Apple [https://developer.apple.com/downloads/index.action?q=Kernel%20Debug%20Kit here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
$ gdb /Volumes/Kernelit/mach_kernel&lt;br /&gt;
(gdb) source /Volumes/KernelDebugKit/kgmacros&lt;br /&gt;
(gdb) target remote-kdp&lt;br /&gt;
(gdb) kdp-reattach  192.168.30.133   # obviously use the IP of your target / crashed VM&lt;br /&gt;
(gdb) showallkmods&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Find the addresses for ZFS and SPL modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;^Z&amp;lt;/code&amp;gt; to suspend gdb, or, use another terminal&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
^Z&lt;br /&gt;
$ sudo kextutil -s /tmp -n \&lt;br /&gt;
-k /Volumes/KernelDebugKit/mach_kernel \&lt;br /&gt;
-e -r /Volumes/KernelDebugKit module/zfs/zfs.kext/ \&lt;br /&gt;
../spl/module/spl/spl.kext/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then resume gdb, or go back to gdb terminal.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
$ fg&lt;br /&gt;
(gdb) set kext-symbol-file-path /tmp&lt;br /&gt;
(gdb) add-kext /tmp/spl.kext &lt;br /&gt;
(gdb) add-kext /tmp/zfs.kext&lt;br /&gt;
(gdb) bt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debugging with LLDB ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo &amp;quot;settings set target.load-script-from-symbol-file true&amp;quot; &amp;gt;&amp;gt; ~/.lldbinit&lt;br /&gt;
$ lldb /Volumes/KernelDebugKit/mach_kernel&lt;br /&gt;
(lldb) kdp-remote  192.168.30.146&lt;br /&gt;
(lldb) showallkmods&lt;br /&gt;
(lldb) addkext -F /tmp/spl.kext/Contents/MacOS/spl 0xffffff7f8ebb0000   (Address from showallkmods)&lt;br /&gt;
(lldb) addkext -F /tmp/zfs.kext/Contents/MacOS/zfs 0xffffff7f8ebbf000&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then follow the guide for GDB above.&lt;br /&gt;
&lt;br /&gt;
=== Non-panic ===&lt;br /&gt;
&lt;br /&gt;
If you prefer to work in GDB, you can always panic a kernel with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo dtrace -w -n &amp;quot;BEGIN{ panic();}&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But this was revealing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo /usr/libexec/stackshot -i -f /tmp/stackshot.log &lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -w /tmp/trace.txt&lt;br /&gt;
$ less /tmp/trace.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that my hang is here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
PID: 156&lt;br /&gt;
    Process: zpool&lt;br /&gt;
    Thread ID: 0x4e2&lt;br /&gt;
    Thread state: 0x9 == TH_WAIT |TH_UNINT &lt;br /&gt;
    Thread wait_event: 0xffffff8006608a6c&lt;br /&gt;
    Kernel stack: &lt;br /&gt;
    machine_switch_context (in mach_kernel) + 366 (0xffffff80002b3d3e)&lt;br /&gt;
      0xffffff800022e711 (in mach_kernel) + 1281 (0xffffff800022e711)&lt;br /&gt;
        thread_block_reason (in mach_kernel) + 300 (0xffffff800022d9dc)&lt;br /&gt;
          lck_mtx_sleep (in mach_kernel) + 78 (0xffffff80002265ce)&lt;br /&gt;
            0xffffff8000569ef6 (in mach_kernel) + 246 (0xffffff8000569ef6)&lt;br /&gt;
              msleep (in mach_kernel) + 116 (0xffffff800056a2e4)&lt;br /&gt;
                0xffffff7f80e52a76 (0xffffff7f80e52a76)&lt;br /&gt;
                  0xffffff7f80e53fae (0xffffff7f80e53fae)&lt;br /&gt;
                    0xffffff7f80e54173 (0xffffff7f80e54173)&lt;br /&gt;
                      0xffffff7f80f1a870 (0xffffff7f80f1a870)&lt;br /&gt;
                        0xffffff7f80f2bb4e (0xffffff7f80f2bb4e)&lt;br /&gt;
                          0xffffff7f80f1a9b7 (0xffffff7f80f1a9b7)&lt;br /&gt;
                            0xffffff7f80f1b65f (0xffffff7f80f1b65f)&lt;br /&gt;
                              0xffffff7f80f042ee (0xffffff7f80f042ee)&lt;br /&gt;
                                0xffffff7f80f45c5b (0xffffff7f80f45c5b)&lt;br /&gt;
                                  0xffffff7f80f4ce92 (0xffffff7f80f4ce92)&lt;br /&gt;
                                    spec_ioctl (in mach_kernel) + 157 (0xffffff8000320bfd)&lt;br /&gt;
                                      VNOP_IOCTL (in mach_kernel) + 244 (0xffffff8000311e84)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a shame that it only shows the kernel symbols, and not inside SPL and ZFS, but we can ask it to load another sym file. (Alas, it cannot handle multiple symbols files. Fix this Apple.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo kextstat #grab the addresses of SPL and ZFS again&lt;br /&gt;
$ sudo kextutil -s /tmp -n -k /Volumes/KernelDebugKit/mach_kernel \&lt;br /&gt;
-e -r /Volumes/KernelDebugKit module/zfs/zfs.kext/ ../spl/module/spl/spl.kext/ &lt;br /&gt;
&lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -k /tmp/net.lundman.spl.sym&lt;br /&gt;
              0xffffff800056a2e4 (0xffffff800056a2e4)&lt;br /&gt;
                spl_cv_wait (in net.lundman.spl.sym) + 54 (0xffffff7f80e52a76)&lt;br /&gt;
                  taskq_wait (in net.lundman.spl.sym) + 78 (0xffffff7f80e53fae)&lt;br /&gt;
                    taskq_destroy (in net.lundman.spl.sym) + 35 (0xffffff7f80e54173)&lt;br /&gt;
                      0xffffff7f80f1a870 (0xffffff7f80f1a870)&lt;br /&gt;
&lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -k /tmp/net.lundman.zfs.sym&lt;br /&gt;
                    0xffffff7f80e54173 (0xffffff7f80e54173)&lt;br /&gt;
                      vdev_open_children (in net.lundman.zfs.sym) + 336 (0xffffff7f80f1a870)&lt;br /&gt;
                        vdev_root_open (in net.lundman.zfs.sym) + 94 (0xffffff7f80f2bb4e)&lt;br /&gt;
                          vdev_open (in net.lundman.zfs.sym) + 311 (0xffffff7f80f1a9b7)&lt;br /&gt;
                            vdev_create (in net.lundman.zfs.sym) + 31 (0xffffff7f80f1b65f)&lt;br /&gt;
                              spa_create (in net.lundman.zfs.sym) + 878 (0xffffff7f80f042ee)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voilà!&lt;br /&gt;
&lt;br /&gt;
=== Memory leaks ===&lt;br /&gt;
&lt;br /&gt;
In some cases, you may suspect memory issues, for instance if you saw the following panic:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
panic(cpu 1 caller 0xffffff80002438d8): &amp;quot;zalloc: \&amp;quot;kalloc.1024\&amp;quot; (100535 elements) retry fail 3, kfree_nop_count: 0&amp;quot;@/SourceCache/xnu/xnu-2050.7.9/osfmk/kern/zalloc.c:1826&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To debug this, you can attach GDB and use the zprint command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) zprint&lt;br /&gt;
ZONE                   COUNT   TOT_SZ   MAX_SZ   ELT_SZ ALLOC_SZ         TOT_ALLOC         TOT_FREE NAME&lt;br /&gt;
0xffffff8002a89250   1620133  18c1000  22a3599       16     1000         125203838        123583705 kalloc.16 CX&lt;br /&gt;
0xffffff8006306c50    110335   35f000   4ce300       32     1000          13634985         13524650 kalloc.32 CX&lt;br /&gt;
0xffffff8006306a00    133584   82a000   e6a900       64     1000          26510120         26376536 kalloc.64 CX&lt;br /&gt;
0xffffff80063067b0    610090  4a84000  614f4c0      128     1000          50524515         49914425 kalloc.128 CX&lt;br /&gt;
0xffffff8006306560   1070398 121a2000 1b5e4d60      256     1000          72534632         71464234 kalloc.256 CX&lt;br /&gt;
0xffffff8006306310    399302  d423000  daf26b0      512     1000          39231204         38831902 kalloc.512 CX&lt;br /&gt;
0xffffff80063060c0    100404  6231000  c29e980     1024     1000          22949693         22849289 kalloc.1024 CX&lt;br /&gt;
0xffffff8006305e70       292    9a000   200000     2048     1000          77633725         77633433 kalloc.2048 CX&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, kalloc.256 is suspect.&lt;br /&gt;
&lt;br /&gt;
Reboot kernel with zlog=kalloc.256 on the command line, then we can use&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) findoldest                                                                &lt;br /&gt;
oldest record is at log index 393:&lt;br /&gt;
&lt;br /&gt;
--------------- ALLOC  0xffffff803276ec00 : index 393  :  ztime 21643824 -------------&lt;br /&gt;
0xffffff800024352e &amp;lt;zalloc_canblock+78&amp;gt;:        mov    %eax,-0xcc(%rbp)&lt;br /&gt;
0xffffff80002245bd &amp;lt;get_zone_search+23&amp;gt;:        jmpq   0xffffff80002246d8 &amp;lt;KALLOC_ZINFO_SALLOC+35&amp;gt;&lt;br /&gt;
0xffffff8000224c39 &amp;lt;OSMalloc+89&amp;gt;:       mov    %rax,-0x18(%rbp)&lt;br /&gt;
0xffffff7f80e847df &amp;lt;zfs_kmem_alloc+15&amp;gt;: mov    %rax,%r15&lt;br /&gt;
0xffffff7f80e90649 &amp;lt;arc_buf_alloc+41&amp;gt;:  mov    %rax,-0x28(%rbp)&lt;br /&gt;
and indeed, list any index&lt;br /&gt;
&lt;br /&gt;
(gdb) zstack 394&lt;br /&gt;
&lt;br /&gt;
--------------- ALLOC  0xffffff8032d60700 : index 394  :  ztime 21648810 -------------&lt;br /&gt;
0xffffff800024352e &amp;lt;zalloc_canblock+78&amp;gt;:        mov    %eax,-0xcc(%rbp)&lt;br /&gt;
0xffffff80002245bd &amp;lt;get_zone_search+23&amp;gt;:        jmpq   0xffffff80002246d8 &amp;lt;KALLOC_ZINFO_SALLOC+35&amp;gt;&lt;br /&gt;
0xffffff8000224c39 &amp;lt;OSMalloc+89&amp;gt;:       mov    %rax,-0x18(%rbp)&lt;br /&gt;
0xffffff7f80e847df &amp;lt;zfs_kmem_alloc+15&amp;gt;: mov    %rax,%r15&lt;br /&gt;
0xffffff7f80e90649 &amp;lt;arc_buf_alloc+41&amp;gt;:  mov    %rax,-0x28(%rbp)&lt;br /&gt;
How many times was zfs_kmem_alloc involved in the leaked allocs?&lt;br /&gt;
&lt;br /&gt;
(gdb) countpcs 0xffffff7f80e847df&lt;br /&gt;
occurred 3999 times in log (100% of records)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At least we know it is our fault.&lt;br /&gt;
&lt;br /&gt;
How many times is it arc_buf_alloc?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) countpcs 0xffffff7f80e90649&lt;br /&gt;
occurred 2390 times in log (59% of records)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Flamegraphs ==&lt;br /&gt;
&lt;br /&gt;
Huge thanks to [http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html BrendanGregg] for so much of the dtrace magic.&lt;br /&gt;
&lt;br /&gt;
dtrace the kernel while running a command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo dtrace -x stackframes=100 -n 'profile-997 /arg0/ {&lt;br /&gt;
    @[stack()] = count(); } tick-60s { exit(0); }' -o out.stacks&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will run for 60 seconds.&lt;br /&gt;
&lt;br /&gt;
Convert it to a flamegraph:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./stackcollapse.pl out.stacks &amp;gt; out.folded&lt;br /&gt;
$ ./flamegraph.pl out.folded &amp;gt; out.svg&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is &amp;lt;code&amp;gt;rsync -a /usr/ /BOOM/deletea/&amp;lt;/code&amp;gt; running:&lt;br /&gt;
&lt;br /&gt;
[[File:rsyncflamegraph.svg|thumb|rsync flamegraph]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Or running '''Bonnie++''' in various stages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed-hover&amp;quot;&amp;gt;&lt;br /&gt;
File:create.svg|Create files in sequential order|alt=[[File:create.svg]]&lt;br /&gt;
File:stat.svg|Stat files in sequential order|alt=Stat files in sequential order&lt;br /&gt;
File:delete.svg|Delete files in sequential order|alt=Delete files in sequential order&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:VX_create.svg|thumb|Create files in sequential order]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:iozone.svg|thumb|IOzone flamegraph]]&lt;br /&gt;
&lt;br /&gt;
[[File:iozoneX.svg|thumb|IOzone flamegraph (untrimmed)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------&lt;br /&gt;
&lt;br /&gt;
== Iozone ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Quick peek at how they compare, just to see how much we should improve it by.&lt;br /&gt;
&lt;br /&gt;
HFS+ and ZFS were created on the same virtual disk in VMware. Of course, this is not ideal testing specs, but should serve as an indicator. &lt;br /&gt;
&lt;br /&gt;
The pool was created with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool create -f -o ashift=12 \&lt;br /&gt;
-O atime=off \&lt;br /&gt;
-O casesensitivity=insensitive \&lt;br /&gt;
-O normalization=formD \&lt;br /&gt;
BOOM /dev/disk1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the HFS+ file system was created with the standard OS X Disk Utility.app, with everything default (journaled, case-insensitive).&lt;br /&gt;
&lt;br /&gt;
'''Iozone''' was run with standard automode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo iozone -a -b outfile.xls&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:hfs2_read.png|thumb|HFS+ read]]&lt;br /&gt;
[[File:hfs2_write.png|thumb|HFS+ write]]&lt;br /&gt;
[[File:zfs2_read.png|thumb|ZFS read]]&lt;br /&gt;
[[File:zfs2_write.png|thumb|ZFS write]]&lt;br /&gt;
&lt;br /&gt;
As a guess, writes need to double, and reads need to triple.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== VFS ===&lt;br /&gt;
&lt;br /&gt;
[[VFS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File-based zpools ==&lt;br /&gt;
&lt;br /&gt;
* create 2 files (each 100 MB) to be used as block devices:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ dd if=/dev/zero bs=1m count=100 of=vdisk1&lt;br /&gt;
$ dd if=/dev/zero bs=1m count=100 of=vdisk2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* attach files as raw disk images:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount vdisk1&lt;br /&gt;
/dev/disk2&lt;br /&gt;
$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount vdisk2&lt;br /&gt;
/dev/disk3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* create mirrored zpool:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool create -f -o ashift=12 -O casesensitivity=insensitive -O normalization=formD tank mirror disk2 disk3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* show zpool:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool status&lt;br /&gt;
  pool: tank&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
  scan: none requested&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME        STATE     READ WRITE CKSUM&lt;br /&gt;
	tank        ONLINE       0     0     0&lt;br /&gt;
	  mirror-0  ONLINE       0     0     0&lt;br /&gt;
	    disk2   ONLINE       0     0     0&lt;br /&gt;
	    disk3   ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* test ZFS features, find bugs, ...&lt;br /&gt;
&lt;br /&gt;
* export zpool:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool export tank&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* detach raw images:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ hdiutil detach disk2&lt;br /&gt;
&amp;quot;disk2&amp;quot; unmounted.&lt;br /&gt;
&amp;quot;disk2&amp;quot; ejected.&lt;br /&gt;
$ hdiutil detach disk3&lt;br /&gt;
&amp;quot;disk3&amp;quot; unmounted.&lt;br /&gt;
&amp;quot;disk3&amp;quot; ejected.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>92.225.159.249</name></author>	</entry>

	<entry>
		<id>https://openzfsonosx.org/wiki/Development</id>
		<title>Development</title>
		<link rel="alternate" type="text/html" href="https://openzfsonosx.org/wiki/Development"/>
				<updated>2014-06-02T22:44:42Z</updated>
		
		<summary type="html">&lt;p&gt;92.225.159.249: /* File-based zpools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:O3X development]]&lt;br /&gt;
You should also familiarize yourself with the [[Project_roadmap|project roadmap]] so that you can put the technical details here in context.&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
&lt;br /&gt;
=== Debugging with GDB ===&lt;br /&gt;
&lt;br /&gt;
Dealing with [[Panic|panics]].&lt;br /&gt;
&lt;br /&gt;
Apple's documentation: https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptDebugger/debug_tutorial.html&lt;br /&gt;
&lt;br /&gt;
Boot target VM with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo nvram boot-args=&amp;quot;-v keepsyms=y debug=0x144&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make it panic.&lt;br /&gt;
&lt;br /&gt;
On your development machine, you will need the Kernel Debug Kit. Download it from Apple [https://developer.apple.com/downloads/index.action?q=Kernel%20Debug%20Kit here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
$ gdb /Volumes/Kernelit/mach_kernel&lt;br /&gt;
(gdb) source /Volumes/KernelDebugKit/kgmacros&lt;br /&gt;
(gdb) target remote-kdp&lt;br /&gt;
(gdb) kdp-reattach  192.168.30.133   # obviously use the IP of your target / crashed VM&lt;br /&gt;
(gdb) showallkmods&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Find the addresses for ZFS and SPL modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;^Z&amp;lt;/code&amp;gt; to suspend gdb, or, use another terminal&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
^Z&lt;br /&gt;
$ sudo kextutil -s /tmp -n \&lt;br /&gt;
-k /Volumes/KernelDebugKit/mach_kernel \&lt;br /&gt;
-e -r /Volumes/KernelDebugKit module/zfs/zfs.kext/ \&lt;br /&gt;
../spl/module/spl/spl.kext/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then resume gdb, or go back to gdb terminal.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
$ fg&lt;br /&gt;
(gdb) set kext-symbol-file-path /tmp&lt;br /&gt;
(gdb) add-kext /tmp/spl.kext &lt;br /&gt;
(gdb) add-kext /tmp/zfs.kext&lt;br /&gt;
(gdb) bt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debugging with LLDB ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo &amp;quot;settings set target.load-script-from-symbol-file true&amp;quot; &amp;gt;&amp;gt; ~/.lldbinit&lt;br /&gt;
$ lldb /Volumes/KernelDebugKit/mach_kernel&lt;br /&gt;
(lldb) kdp-remote  192.168.30.146&lt;br /&gt;
(lldb) showallkmods&lt;br /&gt;
(lldb) addkext -F /tmp/spl.kext/Contents/MacOS/spl 0xffffff7f8ebb0000   (Address from showallkmods)&lt;br /&gt;
(lldb) addkext -F /tmp/zfs.kext/Contents/MacOS/zfs 0xffffff7f8ebbf000&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then follow the guide for GDB above.&lt;br /&gt;
&lt;br /&gt;
=== Non-panic ===&lt;br /&gt;
&lt;br /&gt;
If you prefer to work in GDB, you can always panic a kernel with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo dtrace -w -n &amp;quot;BEGIN{ panic();}&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But this was revealing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo /usr/libexec/stackshot -i -f /tmp/stackshot.log &lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -w /tmp/trace.txt&lt;br /&gt;
$ less /tmp/trace.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that my hang is here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
PID: 156&lt;br /&gt;
    Process: zpool&lt;br /&gt;
    Thread ID: 0x4e2&lt;br /&gt;
    Thread state: 0x9 == TH_WAIT |TH_UNINT &lt;br /&gt;
    Thread wait_event: 0xffffff8006608a6c&lt;br /&gt;
    Kernel stack: &lt;br /&gt;
    machine_switch_context (in mach_kernel) + 366 (0xffffff80002b3d3e)&lt;br /&gt;
      0xffffff800022e711 (in mach_kernel) + 1281 (0xffffff800022e711)&lt;br /&gt;
        thread_block_reason (in mach_kernel) + 300 (0xffffff800022d9dc)&lt;br /&gt;
          lck_mtx_sleep (in mach_kernel) + 78 (0xffffff80002265ce)&lt;br /&gt;
            0xffffff8000569ef6 (in mach_kernel) + 246 (0xffffff8000569ef6)&lt;br /&gt;
              msleep (in mach_kernel) + 116 (0xffffff800056a2e4)&lt;br /&gt;
                0xffffff7f80e52a76 (0xffffff7f80e52a76)&lt;br /&gt;
                  0xffffff7f80e53fae (0xffffff7f80e53fae)&lt;br /&gt;
                    0xffffff7f80e54173 (0xffffff7f80e54173)&lt;br /&gt;
                      0xffffff7f80f1a870 (0xffffff7f80f1a870)&lt;br /&gt;
                        0xffffff7f80f2bb4e (0xffffff7f80f2bb4e)&lt;br /&gt;
                          0xffffff7f80f1a9b7 (0xffffff7f80f1a9b7)&lt;br /&gt;
                            0xffffff7f80f1b65f (0xffffff7f80f1b65f)&lt;br /&gt;
                              0xffffff7f80f042ee (0xffffff7f80f042ee)&lt;br /&gt;
                                0xffffff7f80f45c5b (0xffffff7f80f45c5b)&lt;br /&gt;
                                  0xffffff7f80f4ce92 (0xffffff7f80f4ce92)&lt;br /&gt;
                                    spec_ioctl (in mach_kernel) + 157 (0xffffff8000320bfd)&lt;br /&gt;
                                      VNOP_IOCTL (in mach_kernel) + 244 (0xffffff8000311e84)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a shame that it only shows the kernel symbols, and not inside SPL and ZFS, but we can ask it to load another sym file. (Alas, it cannot handle multiple symbols files. Fix this Apple.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo kextstat #grab the addresses of SPL and ZFS again&lt;br /&gt;
$ sudo kextutil -s /tmp -n -k /Volumes/KernelDebugKit/mach_kernel \&lt;br /&gt;
-e -r /Volumes/KernelDebugKit module/zfs/zfs.kext/ ../spl/module/spl/spl.kext/ &lt;br /&gt;
&lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -k /tmp/net.lundman.spl.sym&lt;br /&gt;
              0xffffff800056a2e4 (0xffffff800056a2e4)&lt;br /&gt;
                spl_cv_wait (in net.lundman.spl.sym) + 54 (0xffffff7f80e52a76)&lt;br /&gt;
                  taskq_wait (in net.lundman.spl.sym) + 78 (0xffffff7f80e53fae)&lt;br /&gt;
                    taskq_destroy (in net.lundman.spl.sym) + 35 (0xffffff7f80e54173)&lt;br /&gt;
                      0xffffff7f80f1a870 (0xffffff7f80f1a870)&lt;br /&gt;
&lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -k /tmp/net.lundman.zfs.sym&lt;br /&gt;
                    0xffffff7f80e54173 (0xffffff7f80e54173)&lt;br /&gt;
                      vdev_open_children (in net.lundman.zfs.sym) + 336 (0xffffff7f80f1a870)&lt;br /&gt;
                        vdev_root_open (in net.lundman.zfs.sym) + 94 (0xffffff7f80f2bb4e)&lt;br /&gt;
                          vdev_open (in net.lundman.zfs.sym) + 311 (0xffffff7f80f1a9b7)&lt;br /&gt;
                            vdev_create (in net.lundman.zfs.sym) + 31 (0xffffff7f80f1b65f)&lt;br /&gt;
                              spa_create (in net.lundman.zfs.sym) + 878 (0xffffff7f80f042ee)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voilà!&lt;br /&gt;
&lt;br /&gt;
=== Memory leaks ===&lt;br /&gt;
&lt;br /&gt;
In some cases, you may suspect memory issues, for instance if you saw the following panic:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
panic(cpu 1 caller 0xffffff80002438d8): &amp;quot;zalloc: \&amp;quot;kalloc.1024\&amp;quot; (100535 elements) retry fail 3, kfree_nop_count: 0&amp;quot;@/SourceCache/xnu/xnu-2050.7.9/osfmk/kern/zalloc.c:1826&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To debug this, you can attach GDB and use the zprint command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) zprint&lt;br /&gt;
ZONE                   COUNT   TOT_SZ   MAX_SZ   ELT_SZ ALLOC_SZ         TOT_ALLOC         TOT_FREE NAME&lt;br /&gt;
0xffffff8002a89250   1620133  18c1000  22a3599       16     1000         125203838        123583705 kalloc.16 CX&lt;br /&gt;
0xffffff8006306c50    110335   35f000   4ce300       32     1000          13634985         13524650 kalloc.32 CX&lt;br /&gt;
0xffffff8006306a00    133584   82a000   e6a900       64     1000          26510120         26376536 kalloc.64 CX&lt;br /&gt;
0xffffff80063067b0    610090  4a84000  614f4c0      128     1000          50524515         49914425 kalloc.128 CX&lt;br /&gt;
0xffffff8006306560   1070398 121a2000 1b5e4d60      256     1000          72534632         71464234 kalloc.256 CX&lt;br /&gt;
0xffffff8006306310    399302  d423000  daf26b0      512     1000          39231204         38831902 kalloc.512 CX&lt;br /&gt;
0xffffff80063060c0    100404  6231000  c29e980     1024     1000          22949693         22849289 kalloc.1024 CX&lt;br /&gt;
0xffffff8006305e70       292    9a000   200000     2048     1000          77633725         77633433 kalloc.2048 CX&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, kalloc.256 is suspect.&lt;br /&gt;
&lt;br /&gt;
Reboot kernel with zlog=kalloc.256 on the command line, then we can use&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) findoldest                                                                &lt;br /&gt;
oldest record is at log index 393:&lt;br /&gt;
&lt;br /&gt;
--------------- ALLOC  0xffffff803276ec00 : index 393  :  ztime 21643824 -------------&lt;br /&gt;
0xffffff800024352e &amp;lt;zalloc_canblock+78&amp;gt;:        mov    %eax,-0xcc(%rbp)&lt;br /&gt;
0xffffff80002245bd &amp;lt;get_zone_search+23&amp;gt;:        jmpq   0xffffff80002246d8 &amp;lt;KALLOC_ZINFO_SALLOC+35&amp;gt;&lt;br /&gt;
0xffffff8000224c39 &amp;lt;OSMalloc+89&amp;gt;:       mov    %rax,-0x18(%rbp)&lt;br /&gt;
0xffffff7f80e847df &amp;lt;zfs_kmem_alloc+15&amp;gt;: mov    %rax,%r15&lt;br /&gt;
0xffffff7f80e90649 &amp;lt;arc_buf_alloc+41&amp;gt;:  mov    %rax,-0x28(%rbp)&lt;br /&gt;
and indeed, list any index&lt;br /&gt;
&lt;br /&gt;
(gdb) zstack 394&lt;br /&gt;
&lt;br /&gt;
--------------- ALLOC  0xffffff8032d60700 : index 394  :  ztime 21648810 -------------&lt;br /&gt;
0xffffff800024352e &amp;lt;zalloc_canblock+78&amp;gt;:        mov    %eax,-0xcc(%rbp)&lt;br /&gt;
0xffffff80002245bd &amp;lt;get_zone_search+23&amp;gt;:        jmpq   0xffffff80002246d8 &amp;lt;KALLOC_ZINFO_SALLOC+35&amp;gt;&lt;br /&gt;
0xffffff8000224c39 &amp;lt;OSMalloc+89&amp;gt;:       mov    %rax,-0x18(%rbp)&lt;br /&gt;
0xffffff7f80e847df &amp;lt;zfs_kmem_alloc+15&amp;gt;: mov    %rax,%r15&lt;br /&gt;
0xffffff7f80e90649 &amp;lt;arc_buf_alloc+41&amp;gt;:  mov    %rax,-0x28(%rbp)&lt;br /&gt;
How many times was zfs_kmem_alloc involved in the leaked allocs?&lt;br /&gt;
&lt;br /&gt;
(gdb) countpcs 0xffffff7f80e847df&lt;br /&gt;
occurred 3999 times in log (100% of records)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At least we know it is our fault.&lt;br /&gt;
&lt;br /&gt;
How many times is it arc_buf_alloc?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) countpcs 0xffffff7f80e90649&lt;br /&gt;
occurred 2390 times in log (59% of records)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Flamegraphs ==&lt;br /&gt;
&lt;br /&gt;
Huge thanks to [http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html BrendanGregg] for so much of the dtrace magic.&lt;br /&gt;
&lt;br /&gt;
dtrace the kernel while running a command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo dtrace -x stackframes=100 -n 'profile-997 /arg0/ {&lt;br /&gt;
    @[stack()] = count(); } tick-60s { exit(0); }' -o out.stacks&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will run for 60 seconds.&lt;br /&gt;
&lt;br /&gt;
Convert it to a flamegraph:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./stackcollapse.pl out.stacks &amp;gt; out.folded&lt;br /&gt;
$ ./flamegraph.pl out.folded &amp;gt; out.svg&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is &amp;lt;code&amp;gt;rsync -a /usr/ /BOOM/deletea/&amp;lt;/code&amp;gt; running:&lt;br /&gt;
&lt;br /&gt;
[[File:rsyncflamegraph.svg|thumb|rsync flamegraph]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Or running '''Bonnie++''' in various stages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed-hover&amp;quot;&amp;gt;&lt;br /&gt;
File:create.svg|Create files in sequential order|alt=[[File:create.svg]]&lt;br /&gt;
File:stat.svg|Stat files in sequential order|alt=Stat files in sequential order&lt;br /&gt;
File:delete.svg|Delete files in sequential order|alt=Delete files in sequential order&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:VX_create.svg|thumb|Create files in sequential order]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:iozone.svg|thumb|IOzone flamegraph]]&lt;br /&gt;
&lt;br /&gt;
[[File:iozoneX.svg|thumb|IOzone flamegraph (untrimmed)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------&lt;br /&gt;
&lt;br /&gt;
== Iozone ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Quick peek at how they compare, just to see how much we should improve it by.&lt;br /&gt;
&lt;br /&gt;
HFS+ and ZFS were created on the same virtual disk in VMware. Of course, this is not ideal testing specs, but should serve as an indicator. &lt;br /&gt;
&lt;br /&gt;
The pool was created with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool create -f -o ashift=12 \&lt;br /&gt;
-O atime=off \&lt;br /&gt;
-O casesensitivity=insensitive \&lt;br /&gt;
-O normalization=formD \&lt;br /&gt;
BOOM /dev/disk1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the HFS+ file system was created with the standard OS X Disk Utility.app, with everything default (journaled, case-insensitive).&lt;br /&gt;
&lt;br /&gt;
'''Iozone''' was run with standard automode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo iozone -a -b outfile.xls&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:hfs2_read.png|thumb|HFS+ read]]&lt;br /&gt;
[[File:hfs2_write.png|thumb|HFS+ write]]&lt;br /&gt;
[[File:zfs2_read.png|thumb|ZFS read]]&lt;br /&gt;
[[File:zfs2_write.png|thumb|ZFS write]]&lt;br /&gt;
&lt;br /&gt;
As a guess, writes need to double, and reads need to triple.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== VFS ===&lt;br /&gt;
&lt;br /&gt;
[[VFS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File-based zpools ==&lt;br /&gt;
&lt;br /&gt;
* create 2 files (each 100 MB) to be used as block devices:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ dd if=/dev/zero bs=1m count=100 of=vdisk1&lt;br /&gt;
$ dd if=/dev/zero bs=1m count=100 of=vdisk2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* attach files as raw disk images:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount vdisk1&lt;br /&gt;
/dev/disk2&lt;br /&gt;
$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount vdisk2&lt;br /&gt;
/dev/disk3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* create mirrored zpool:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool create -f -o ashift=12 -O casesensitivity=insensitive -O normalization=formD tank mirror disk2 disk3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* show zpool:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool status&lt;br /&gt;
  pool: tank&lt;br /&gt;
 state: ONLINE&lt;br /&gt;
  scan: none requested&lt;br /&gt;
config:&lt;br /&gt;
&lt;br /&gt;
	NAME        STATE     READ WRITE CKSUM&lt;br /&gt;
	tank        ONLINE       0     0     0&lt;br /&gt;
	  mirror-0  ONLINE       0     0     0&lt;br /&gt;
	    disk2   ONLINE       0     0     0&lt;br /&gt;
	    disk3   ONLINE       0     0     0&lt;br /&gt;
&lt;br /&gt;
errors: No known data errors&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>92.225.159.249</name></author>	</entry>

	<entry>
		<id>https://openzfsonosx.org/wiki/Development</id>
		<title>Development</title>
		<link rel="alternate" type="text/html" href="https://openzfsonosx.org/wiki/Development"/>
				<updated>2014-06-02T22:42:17Z</updated>
		
		<summary type="html">&lt;p&gt;92.225.159.249: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:O3X development]]&lt;br /&gt;
You should also familiarize yourself with the [[Project_roadmap|project roadmap]] so that you can put the technical details here in context.&lt;br /&gt;
&lt;br /&gt;
== Kernel ==&lt;br /&gt;
&lt;br /&gt;
=== Debugging with GDB ===&lt;br /&gt;
&lt;br /&gt;
Dealing with [[Panic|panics]].&lt;br /&gt;
&lt;br /&gt;
Apple's documentation: https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptDebugger/debug_tutorial.html&lt;br /&gt;
&lt;br /&gt;
Boot target VM with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo nvram boot-args=&amp;quot;-v keepsyms=y debug=0x144&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Make it panic.&lt;br /&gt;
&lt;br /&gt;
On your development machine, you will need the Kernel Debug Kit. Download it from Apple [https://developer.apple.com/downloads/index.action?q=Kernel%20Debug%20Kit here].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
$ gdb /Volumes/Kernelit/mach_kernel&lt;br /&gt;
(gdb) source /Volumes/KernelDebugKit/kgmacros&lt;br /&gt;
(gdb) target remote-kdp&lt;br /&gt;
(gdb) kdp-reattach  192.168.30.133   # obviously use the IP of your target / crashed VM&lt;br /&gt;
(gdb) showallkmods&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Find the addresses for ZFS and SPL modules.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;^Z&amp;lt;/code&amp;gt; to suspend gdb, or, use another terminal&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
^Z&lt;br /&gt;
$ sudo kextutil -s /tmp -n \&lt;br /&gt;
-k /Volumes/KernelDebugKit/mach_kernel \&lt;br /&gt;
-e -r /Volumes/KernelDebugKit module/zfs/zfs.kext/ \&lt;br /&gt;
../spl/module/spl/spl.kext/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then resume gdb, or go back to gdb terminal.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
$ fg&lt;br /&gt;
(gdb) set kext-symbol-file-path /tmp&lt;br /&gt;
(gdb) add-kext /tmp/spl.kext &lt;br /&gt;
(gdb) add-kext /tmp/zfs.kext&lt;br /&gt;
(gdb) bt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Debugging with LLDB ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo &amp;quot;settings set target.load-script-from-symbol-file true&amp;quot; &amp;gt;&amp;gt; ~/.lldbinit&lt;br /&gt;
$ lldb /Volumes/KernelDebugKit/mach_kernel&lt;br /&gt;
(lldb) kdp-remote  192.168.30.146&lt;br /&gt;
(lldb) showallkmods&lt;br /&gt;
(lldb) addkext -F /tmp/spl.kext/Contents/MacOS/spl 0xffffff7f8ebb0000   (Address from showallkmods)&lt;br /&gt;
(lldb) addkext -F /tmp/zfs.kext/Contents/MacOS/zfs 0xffffff7f8ebbf000&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then follow the guide for GDB above.&lt;br /&gt;
&lt;br /&gt;
=== Non-panic ===&lt;br /&gt;
&lt;br /&gt;
If you prefer to work in GDB, you can always panic a kernel with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo dtrace -w -n &amp;quot;BEGIN{ panic();}&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
But this was revealing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo /usr/libexec/stackshot -i -f /tmp/stackshot.log &lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -w /tmp/trace.txt&lt;br /&gt;
$ less /tmp/trace.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that my hang is here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
PID: 156&lt;br /&gt;
    Process: zpool&lt;br /&gt;
    Thread ID: 0x4e2&lt;br /&gt;
    Thread state: 0x9 == TH_WAIT |TH_UNINT &lt;br /&gt;
    Thread wait_event: 0xffffff8006608a6c&lt;br /&gt;
    Kernel stack: &lt;br /&gt;
    machine_switch_context (in mach_kernel) + 366 (0xffffff80002b3d3e)&lt;br /&gt;
      0xffffff800022e711 (in mach_kernel) + 1281 (0xffffff800022e711)&lt;br /&gt;
        thread_block_reason (in mach_kernel) + 300 (0xffffff800022d9dc)&lt;br /&gt;
          lck_mtx_sleep (in mach_kernel) + 78 (0xffffff80002265ce)&lt;br /&gt;
            0xffffff8000569ef6 (in mach_kernel) + 246 (0xffffff8000569ef6)&lt;br /&gt;
              msleep (in mach_kernel) + 116 (0xffffff800056a2e4)&lt;br /&gt;
                0xffffff7f80e52a76 (0xffffff7f80e52a76)&lt;br /&gt;
                  0xffffff7f80e53fae (0xffffff7f80e53fae)&lt;br /&gt;
                    0xffffff7f80e54173 (0xffffff7f80e54173)&lt;br /&gt;
                      0xffffff7f80f1a870 (0xffffff7f80f1a870)&lt;br /&gt;
                        0xffffff7f80f2bb4e (0xffffff7f80f2bb4e)&lt;br /&gt;
                          0xffffff7f80f1a9b7 (0xffffff7f80f1a9b7)&lt;br /&gt;
                            0xffffff7f80f1b65f (0xffffff7f80f1b65f)&lt;br /&gt;
                              0xffffff7f80f042ee (0xffffff7f80f042ee)&lt;br /&gt;
                                0xffffff7f80f45c5b (0xffffff7f80f45c5b)&lt;br /&gt;
                                  0xffffff7f80f4ce92 (0xffffff7f80f4ce92)&lt;br /&gt;
                                    spec_ioctl (in mach_kernel) + 157 (0xffffff8000320bfd)&lt;br /&gt;
                                      VNOP_IOCTL (in mach_kernel) + 244 (0xffffff8000311e84)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a shame that it only shows the kernel symbols, and not inside SPL and ZFS, but we can ask it to load another sym file. (Alas, it cannot handle multiple symbols files. Fix this Apple.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo kextstat #grab the addresses of SPL and ZFS again&lt;br /&gt;
$ sudo kextutil -s /tmp -n -k /Volumes/KernelDebugKit/mach_kernel \&lt;br /&gt;
-e -r /Volumes/KernelDebugKit module/zfs/zfs.kext/ ../spl/module/spl/spl.kext/ &lt;br /&gt;
&lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -k /tmp/net.lundman.spl.sym&lt;br /&gt;
              0xffffff800056a2e4 (0xffffff800056a2e4)&lt;br /&gt;
                spl_cv_wait (in net.lundman.spl.sym) + 54 (0xffffff7f80e52a76)&lt;br /&gt;
                  taskq_wait (in net.lundman.spl.sym) + 78 (0xffffff7f80e53fae)&lt;br /&gt;
                    taskq_destroy (in net.lundman.spl.sym) + 35 (0xffffff7f80e54173)&lt;br /&gt;
                      0xffffff7f80f1a870 (0xffffff7f80f1a870)&lt;br /&gt;
&lt;br /&gt;
$ sudo symstacks.rb -f /tmp/stackshot.log -s -k /tmp/net.lundman.zfs.sym&lt;br /&gt;
                    0xffffff7f80e54173 (0xffffff7f80e54173)&lt;br /&gt;
                      vdev_open_children (in net.lundman.zfs.sym) + 336 (0xffffff7f80f1a870)&lt;br /&gt;
                        vdev_root_open (in net.lundman.zfs.sym) + 94 (0xffffff7f80f2bb4e)&lt;br /&gt;
                          vdev_open (in net.lundman.zfs.sym) + 311 (0xffffff7f80f1a9b7)&lt;br /&gt;
                            vdev_create (in net.lundman.zfs.sym) + 31 (0xffffff7f80f1b65f)&lt;br /&gt;
                              spa_create (in net.lundman.zfs.sym) + 878 (0xffffff7f80f042ee)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voilà!&lt;br /&gt;
&lt;br /&gt;
=== Memory leaks ===&lt;br /&gt;
&lt;br /&gt;
In some cases, you may suspect memory issues, for instance if you saw the following panic:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
panic(cpu 1 caller 0xffffff80002438d8): &amp;quot;zalloc: \&amp;quot;kalloc.1024\&amp;quot; (100535 elements) retry fail 3, kfree_nop_count: 0&amp;quot;@/SourceCache/xnu/xnu-2050.7.9/osfmk/kern/zalloc.c:1826&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To debug this, you can attach GDB and use the zprint command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) zprint&lt;br /&gt;
ZONE                   COUNT   TOT_SZ   MAX_SZ   ELT_SZ ALLOC_SZ         TOT_ALLOC         TOT_FREE NAME&lt;br /&gt;
0xffffff8002a89250   1620133  18c1000  22a3599       16     1000         125203838        123583705 kalloc.16 CX&lt;br /&gt;
0xffffff8006306c50    110335   35f000   4ce300       32     1000          13634985         13524650 kalloc.32 CX&lt;br /&gt;
0xffffff8006306a00    133584   82a000   e6a900       64     1000          26510120         26376536 kalloc.64 CX&lt;br /&gt;
0xffffff80063067b0    610090  4a84000  614f4c0      128     1000          50524515         49914425 kalloc.128 CX&lt;br /&gt;
0xffffff8006306560   1070398 121a2000 1b5e4d60      256     1000          72534632         71464234 kalloc.256 CX&lt;br /&gt;
0xffffff8006306310    399302  d423000  daf26b0      512     1000          39231204         38831902 kalloc.512 CX&lt;br /&gt;
0xffffff80063060c0    100404  6231000  c29e980     1024     1000          22949693         22849289 kalloc.1024 CX&lt;br /&gt;
0xffffff8006305e70       292    9a000   200000     2048     1000          77633725         77633433 kalloc.2048 CX&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, kalloc.256 is suspect.&lt;br /&gt;
&lt;br /&gt;
Reboot kernel with zlog=kalloc.256 on the command line, then we can use&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) findoldest                                                                &lt;br /&gt;
oldest record is at log index 393:&lt;br /&gt;
&lt;br /&gt;
--------------- ALLOC  0xffffff803276ec00 : index 393  :  ztime 21643824 -------------&lt;br /&gt;
0xffffff800024352e &amp;lt;zalloc_canblock+78&amp;gt;:        mov    %eax,-0xcc(%rbp)&lt;br /&gt;
0xffffff80002245bd &amp;lt;get_zone_search+23&amp;gt;:        jmpq   0xffffff80002246d8 &amp;lt;KALLOC_ZINFO_SALLOC+35&amp;gt;&lt;br /&gt;
0xffffff8000224c39 &amp;lt;OSMalloc+89&amp;gt;:       mov    %rax,-0x18(%rbp)&lt;br /&gt;
0xffffff7f80e847df &amp;lt;zfs_kmem_alloc+15&amp;gt;: mov    %rax,%r15&lt;br /&gt;
0xffffff7f80e90649 &amp;lt;arc_buf_alloc+41&amp;gt;:  mov    %rax,-0x28(%rbp)&lt;br /&gt;
and indeed, list any index&lt;br /&gt;
&lt;br /&gt;
(gdb) zstack 394&lt;br /&gt;
&lt;br /&gt;
--------------- ALLOC  0xffffff8032d60700 : index 394  :  ztime 21648810 -------------&lt;br /&gt;
0xffffff800024352e &amp;lt;zalloc_canblock+78&amp;gt;:        mov    %eax,-0xcc(%rbp)&lt;br /&gt;
0xffffff80002245bd &amp;lt;get_zone_search+23&amp;gt;:        jmpq   0xffffff80002246d8 &amp;lt;KALLOC_ZINFO_SALLOC+35&amp;gt;&lt;br /&gt;
0xffffff8000224c39 &amp;lt;OSMalloc+89&amp;gt;:       mov    %rax,-0x18(%rbp)&lt;br /&gt;
0xffffff7f80e847df &amp;lt;zfs_kmem_alloc+15&amp;gt;: mov    %rax,%r15&lt;br /&gt;
0xffffff7f80e90649 &amp;lt;arc_buf_alloc+41&amp;gt;:  mov    %rax,-0x28(%rbp)&lt;br /&gt;
How many times was zfs_kmem_alloc involved in the leaked allocs?&lt;br /&gt;
&lt;br /&gt;
(gdb) countpcs 0xffffff7f80e847df&lt;br /&gt;
occurred 3999 times in log (100% of records)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At least we know it is our fault.&lt;br /&gt;
&lt;br /&gt;
How many times is it arc_buf_alloc?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(gdb) countpcs 0xffffff7f80e90649&lt;br /&gt;
occurred 2390 times in log (59% of records)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Flamegraphs ==&lt;br /&gt;
&lt;br /&gt;
Huge thanks to [http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html BrendanGregg] for so much of the dtrace magic.&lt;br /&gt;
&lt;br /&gt;
dtrace the kernel while running a command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo dtrace -x stackframes=100 -n 'profile-997 /arg0/ {&lt;br /&gt;
    @[stack()] = count(); } tick-60s { exit(0); }' -o out.stacks&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It will run for 60 seconds.&lt;br /&gt;
&lt;br /&gt;
Convert it to a flamegraph:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ./stackcollapse.pl out.stacks &amp;gt; out.folded&lt;br /&gt;
$ ./flamegraph.pl out.folded &amp;gt; out.svg&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is &amp;lt;code&amp;gt;rsync -a /usr/ /BOOM/deletea/&amp;lt;/code&amp;gt; running:&lt;br /&gt;
&lt;br /&gt;
[[File:rsyncflamegraph.svg|thumb|rsync flamegraph]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Or running '''Bonnie++''' in various stages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed-hover&amp;quot;&amp;gt;&lt;br /&gt;
File:create.svg|Create files in sequential order|alt=[[File:create.svg]]&lt;br /&gt;
File:stat.svg|Stat files in sequential order|alt=Stat files in sequential order&lt;br /&gt;
File:delete.svg|Delete files in sequential order|alt=Delete files in sequential order&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:VX_create.svg|thumb|Create files in sequential order]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:iozone.svg|thumb|IOzone flamegraph]]&lt;br /&gt;
&lt;br /&gt;
[[File:iozoneX.svg|thumb|IOzone flamegraph (untrimmed)]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
------&lt;br /&gt;
&lt;br /&gt;
== Iozone ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Quick peek at how they compare, just to see how much we should improve it by.&lt;br /&gt;
&lt;br /&gt;
HFS+ and ZFS were created on the same virtual disk in VMware. Of course, this is not ideal testing specs, but should serve as an indicator. &lt;br /&gt;
&lt;br /&gt;
The pool was created with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sudo zpool create -f -o ashift=12 \&lt;br /&gt;
-O atime=off \&lt;br /&gt;
-O casesensitivity=insensitive \&lt;br /&gt;
-O normalization=formD \&lt;br /&gt;
BOOM /dev/disk1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the HFS+ file system was created with the standard OS X Disk Utility.app, with everything default (journaled, case-insensitive).&lt;br /&gt;
&lt;br /&gt;
'''Iozone''' was run with standard automode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo iozone -a -b outfile.xls&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:hfs2_read.png|thumb|HFS+ read]]&lt;br /&gt;
[[File:hfs2_write.png|thumb|HFS+ write]]&lt;br /&gt;
[[File:zfs2_read.png|thumb|ZFS read]]&lt;br /&gt;
[[File:zfs2_write.png|thumb|ZFS write]]&lt;br /&gt;
&lt;br /&gt;
As a guess, writes need to double, and reads need to triple.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== VFS ===&lt;br /&gt;
&lt;br /&gt;
[[VFS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== File-based zpools ==&lt;br /&gt;
&lt;br /&gt;
* create 2 files (each 100 MB) to be used as block devices:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ dd if=/dev/zero bs=1m count=100 of=vdisk1&lt;br /&gt;
$ dd if=/dev/zero bs=1m count=100 of=vdisk2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* attach files as raw disk images:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount vdisk1&lt;br /&gt;
/dev/disk2&lt;br /&gt;
$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount vdisk2&lt;br /&gt;
/dev/disk3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* check&lt;/div&gt;</summary>
		<author><name>92.225.159.249</name></author>	</entry>

	</feed>