<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.8.3">Jekyll</generator><link href="https://tim.palpant.us/feed.xml" rel="self" type="application/atom+xml" /><link href="https://tim.palpant.us/" rel="alternate" type="text/html" hreflang="en" /><updated>2023-05-02T17:54:58-05:00</updated><id>https://tim.palpant.us/feed.xml</id><title type="html">the working iron never rusts</title><subtitle>Side projects and stories.
</subtitle><author><name>Timothy Palpant</name><email>tim@palpant.us</email></author><entry><title type="html">NVDAGPUWakeHandler: Disabling the NVIDIA graphics card on a MacBook Pro 10,1 (2012 retina)</title><link href="https://tim.palpant.us/sysadmin/macos/2018/09/09/nvda-gpu-wake-handler/" rel="alternate" type="text/html" title="NVDAGPUWakeHandler: Disabling the NVIDIA graphics card on a MacBook Pro 10,1 (2012 retina)" /><published>2018-09-09T18:05:00-05:00</published><updated>2018-09-09T18:05:00-05:00</updated><id>https://tim.palpant.us/sysadmin/macos/2018/09/09/nvda-gpu-wake-handler</id><content type="html" xml:base="https://tim.palpant.us/sysadmin/macos/2018/09/09/nvda-gpu-wake-handler/">&lt;p&gt;On Friday my laptop stopped turning on normally, leaving me stuck with a black screen.
The machine was still booting up (I could hear the chimes and the keyboard
backlight worked), but no screen image or backlight whatsoever.&lt;/p&gt;

&lt;p&gt;After taking it to the Apple Store, where they told me it was a Logic board failure,
I learned that this is a &lt;a href=&quot;https://www.apple.com/support/macbookpro-videoissues/&quot;&gt;known issue&lt;/a&gt;
with this generation of MacBooks from 2011-2013. It stemms from the use of a lead-free solder
that results in premature failure of the discrete graphics chips. Unfortunately,
the replacement period ended in 2016.&lt;/p&gt;

&lt;p&gt;However, laptops from this period also contain an integrated GPU as part of the
Intel Core i5/i7 processor. This GPU is used during normal workloads to improve
battery life, and the discrete NVIDIA GeForce 650M is powered down by a controller
chip called the &lt;code class=&quot;highlighter-rouge&quot;&gt;gmux&lt;/code&gt;. This made me to hope that by forcing the NVIDIA GPU to power down I could regain use of my
laptop with only the integrated GPU. To do this, I adapted a macOS kernel extension
derived from the source code for the Linux gmux driver. It’s available on Github
as &lt;a href=&quot;https://github.com/timpalpant/NVDAGPUWakeHandler&quot;&gt;NVDAGPUWakeHandler&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;modifications-to-only-use-the-integrated-gpu&quot;&gt;Modifications to only use the Integrated GPU&lt;/h1&gt;

&lt;h2 id=&quot;prefer-intel-gpu-on-boot-with-nvram-parameter&quot;&gt;Prefer Intel GPU on boot with NVRAM parameter&lt;/h2&gt;

&lt;p&gt;The MacBook boots with EFI, and hackers have found the following NVRAM parameter
can be used to “prefer” the integrated GPU during startup:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo nvram fa4ce28d-b62f-4c99-9cc3-6815686e30f9:gpu-power-prefs=%01%00%00%00
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For me, this restored the ability to boot up normally.&lt;/p&gt;

&lt;h2 id=&quot;disable-nvidia-gpu-in-bios&quot;&gt;Disable NVIDIA GPU in BIOS&lt;/h2&gt;

&lt;p&gt;It is possible to power down the gpu &lt;a href=&quot;https://gist.github.com/blackgate/17ac402e35d2f7e0f1c9708db3dc7a44&quot;&gt;during boot&lt;/a&gt;
using a custom bootloader.&lt;/p&gt;

&lt;p&gt;NOTE: The instructions for this need to be modified for the Retina MBP.
The GRUB config for High Sierra / Mojave should be:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;set timeout=10
menuentry &quot;macOS&quot; {
  outb 0x7c2 1
  outb 0x7d4 0x28
  outb 0x7c2 2
  outb 0x7d4 0x10
  outb 0x7c2 2
  outb 0x7d4 0x40

  outb 0x7c2 1
  outb 0x7d4 0x50
  outb 0x7c2 0
  outb 0x7d4 0x50
  exit
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;(Adapted from &lt;a href=&quot;https://forums.macrumors.com/threads/disable-a-failed-amd-gpu-on-a-2011-macbook-pro-grub-solution.2087527/page-4#post-25510228&quot;&gt;this post&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;After booting, I could see that only the integrated GPU was present in System Profiler:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/nvda-kext/igpu-only.png&quot; alt=&quot;One GPU&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;disable-nvidia-gpu-after-waking-from-sleep&quot;&gt;Disable NVIDIA GPU after waking from sleep&lt;/h2&gt;

&lt;p&gt;The same sequence of signals can be executed from a Kernel Extension (kext) to
keep the GPU disabled after waking from sleep. I forked &lt;a href=&quot;https://github.com/blackgate/AMDGPUWakeHandler&quot;&gt;AMDGPUWakeHandler&lt;/a&gt;
and modified it to execute the appropriate sequence for the Retina MBP.&lt;/p&gt;

&lt;p&gt;My fork is available on &lt;a href=&quot;https://github.com/timpalpant/NVDAGPUWakeHandler&quot;&gt;GitHub&lt;/a&gt;.
To install the kernel extension, you’ll need to either sign it with your own
Apple developer account or disable &lt;a href=&quot;https://en.wikipedia.org/wiki/System_Integrity_Protection&quot;&gt;SIP&lt;/a&gt;
by booting into Recovery mode (&lt;code class=&quot;highlighter-rouge&quot;&gt;CMD+R&lt;/code&gt; during boot) and running:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;csrutil disable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can verify that SIP is disabled by running &lt;code class=&quot;highlighter-rouge&quot;&gt;csrutil status&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;enable-backlight-after-waking-from-sleep-in-high-sierra-1013--mojave-1014&quot;&gt;Enable backlight after waking from sleep in High Sierra (10.13) / Mojave (10.14)&lt;/h2&gt;

&lt;p&gt;This is sufficient to get the Mac to boot; however, in High Sierra something
has changed such that the screen backlight controller no longer turns on after
waking from sleep. If you hold up a flashlight, you can see that the screen
is on, but with no backlight it appears nearly black. You can also see that
macOS no longer thinks there is any backlight control for this display:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/nvda-kext/no-backlight.png&quot; alt=&quot;No backlight&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Fortunately the &lt;a href=&quot;https://github.com/torvalds/linux/blob/master/drivers/platform/x86/apple-gmux.c&quot;&gt;Linux driver for the GMUX controller&lt;/a&gt;
in the MBP contains code to support modifying the backlight setting. I adapted it for use in
&lt;code class=&quot;highlighter-rouge&quot;&gt;NVDAGPUWakeHandler&lt;/code&gt; to set the backlight to a usable level after waking from
sleep. Note that it’s currently hard-coded in the Kext, so if you prefer a different
brightness setting, you’ll have to adjust it as necessary.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt; TankTheFrank on Github has contributed a patch that allows brightness
to be controlled using the standard brightness keys! See &lt;a href=&quot;https://github.com/TankTheFrank/NativeDisplayBrightness&quot;&gt;NativeDisplayBrightness&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h1&gt;

&lt;p&gt;After installing the kernel extension, wake from sleep seems to be working correctly
and I haven’t had any issues. The biggest insight for me was to see the amazing work
that the Linux kernel devs have put in to reverse engineer and implement drivers
for the rather unique MBP hardware. Despite having no experience with Linux kernel
development the C code for &lt;a href=&quot;https://github.com/torvalds/linux/blob/master/drivers/platform/x86/apple-gmux.c&quot;&gt;apple-gmux.c&lt;/a&gt;
was incredibly well-documented and easy to follow, making it easy to adapt and use
in macOS.&lt;/p&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;p&gt;[1] https://dhavaldalal.wordpress.com/2018/05/29/how-to-disable-failed-discrete-gpu-nvidia-geforce-gt-650m-for-macbook-pro-101-mid-2012-on-high-sierra-10-13-4/&lt;/p&gt;

&lt;p&gt;[2] https://gist.github.com/blackgate/17ac402e35d2f7e0f1c9708db3dc7a44&lt;/p&gt;

&lt;p&gt;[3] https://github.com/blackgate/AMDGPUWakeHandler&lt;/p&gt;

&lt;p&gt;[4] https://forums.macrumors.com/threads/disable-a-failed-amd-gpu-on-a-2011-macbook-pro-grub-solution.2087527/page-7&lt;/p&gt;

&lt;p&gt;[5] https://forums.macrumors.com/threads/force-2011-macbook-pro-8-2-with-failed-amd-gpu-to-always-use-intel-integrated-gpu-efi-variable-fix.2037591/page-81&lt;/p&gt;

&lt;p&gt;[6] https://wiki.archlinux.org/index.php/MacBookPro10,x#Graphics_2&lt;/p&gt;</content><author><name>Timothy Palpant</name><email>tim@palpant.us</email></author><summary type="html">On Friday my laptop stopped turning on normally, leaving me stuck with a black screen. The machine was still booting up (I could hear the chimes and the keyboard backlight worked), but no screen image or backlight whatsoever.</summary></entry><entry><title type="html">Docker for Mac Memory Leak</title><link href="https://tim.palpant.us/sysadmin/devtools/docker/2018/09/08/docker-for-mac/" rel="alternate" type="text/html" title="Docker for Mac Memory Leak" /><published>2018-09-08T18:05:00-05:00</published><updated>2018-09-08T18:05:00-05:00</updated><id>https://tim.palpant.us/sysadmin/devtools/docker/2018/09/08/docker-for-mac</id><content type="html" xml:base="https://tim.palpant.us/sysadmin/devtools/docker/2018/09/08/docker-for-mac/">&lt;p&gt;It seems that the default settings in Docker for Mac do not enforce
any log rotation for services running on the integrated Kubernetes.
This led to a seeming &lt;a href=&quot;https://stackoverflow.com/questions/27628276/docker-daemon-memory-leak-due-to-logs-from-long-running-process&quot;&gt;memory leak&lt;/a&gt; that would eventually crash my
computer for long-running services. While this is somewhat understandable,
given that Docker for Mac is clearly targeted for development, it
still seems like an unfortunate default.&lt;/p&gt;

&lt;p&gt;You can enforce a max size for logs by editing &lt;code class=&quot;highlighter-rouge&quot;&gt;$HOME/.docker/daemon.json&lt;/code&gt;
to include:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;log-opts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;max-size&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;10m&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Timothy Palpant</name><email>tim@palpant.us</email></author><summary type="html">It seems that the default settings in Docker for Mac do not enforce any log rotation for services running on the integrated Kubernetes. This led to a seeming memory leak that would eventually crash my computer for long-running services. While this is somewhat understandable, given that Docker for Mac is clearly targeted for development, it still seems like an unfortunate default.</summary></entry><entry><title type="html">ZFS on macOS</title><link href="https://tim.palpant.us/sysadmin/storage/2018/09/03/zfs/" rel="alternate" type="text/html" title="ZFS on macOS" /><published>2018-09-03T19:12:43-05:00</published><updated>2018-09-03T19:12:43-05:00</updated><id>https://tim.palpant.us/sysadmin/storage/2018/09/03/zfs</id><content type="html" xml:base="https://tim.palpant.us/sysadmin/storage/2018/09/03/zfs/">&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/ZFS&quot;&gt;ZFS&lt;/a&gt; is a filesystem developed at
&lt;a href=&quot;https://en.wikipedia.org/wiki/Sun_Microsystems&quot;&gt;Sun Microsystems&lt;/a&gt;
for their &lt;a href=&quot;https://en.wikipedia.org/wiki/Solaris_(operating_system)&quot;&gt;Solaris&lt;/a&gt; operating system.
This is an experience report from recently setting it up as the filesystem
for my secondary storage drives on macOS.&lt;/p&gt;

&lt;p&gt;In contrast to other common filesystems you may encounter, ZFS is fully transactional and copy-on-write (COW).
At the most basic level, you can imagine it as if the filesystem were a database of small blocks,
indexed in B-trees and checksummed for verification. Notably, the COW design allows nearly
instantaneous “snapshots” to be recorded and incremental backups between them. It also includes
the feature sets of &lt;a href=&quot;https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)&quot;&gt;Logical Volume Management (LVM)&lt;/a&gt;,
&lt;a href=&quot;https://en.wikipedia.org/wiki/RAID&quot;&gt;RAID&lt;/a&gt; (&lt;a href=&quot;https://en.wikipedia.org/wiki/Mdadm&quot;&gt;mdadm&lt;/a&gt;),
caching (&lt;a href=&quot;https://en.wikipedia.org/wiki/Bcache&quot;&gt;bcache&lt;/a&gt;/flashcache), and transparent compression out of the box.&lt;/p&gt;

&lt;p&gt;At one point, ZFS seemed like the future of filesystems, with &lt;a href=&quot;https://arstechnica.com/gadgets/2016/06/zfs-the-other-new-apple-file-system-that-almost-was-until-it-wasnt/&quot;&gt;Apple intending to use it&lt;/a&gt;
in OS X (see: Time Machine). Furthermore, Sun released ZFS as open source under the CDDL license, however
due to some &lt;a href=&quot;https://blog.ubuntu.com/2016/02/18/zfs-licensing-and-linux&quot;&gt;licensing controversy&lt;/a&gt;
it was never merged into the mainline Linux kernel. Thus ZFS was squandered, never to be
enjoyed as widely as might have otherwise been.&lt;/p&gt;

&lt;p&gt;In recent years, it’s become possible to run ZFS on linux through the efforts of the
&lt;a href=&quot;https://zfsonlinux.org&quot;&gt;ZFS on Linux&lt;/a&gt; project, and the incorporation of easy-to-install ZFS
packages in the Ubuntu repos. A related project, &lt;a href=&quot;https://openzfsonosx.org&quot;&gt;OpenZFSOnOSX&lt;/a&gt;, brings ZFS to macOS by using
a &lt;a href=&quot;https://github.com/openzfsonosx/spl&quot;&gt;Solaris Porting Layer (SPL)&lt;/a&gt; to translate Solaris
system calls for the &lt;a href=&quot;https://en.wikipedia.org/wiki/Darwin_(operating_system)#Kernel&quot;&gt;Darwin kernel&lt;/a&gt; on macOS,
allowing them to run ZFS code mostly unchanged. This obviously brings some performance
penalty, but one that is hopefully not too significant on spinning disks, since they
will likely be I/O bound by the disks anyway.&lt;/p&gt;

&lt;h1 id=&quot;installation&quot;&gt;Installation&lt;/h1&gt;

&lt;p&gt;Installation was easy using the provided package on the OpenZFSOnOSX website, or&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew cask &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;openzfs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which installs a few kernel extensions:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;kextstat | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;net.lundman
69    1 0xffffff7f816aa000 0x498      0x498      net.lundman.kernel.dependencies.31 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;12.5.0&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; CF3A4A39-BA8C-4DFF-8BA7-B3C04D69457E
70    1 0xffffff7f816ab000 0x11f5000  0x11f5000  net.lundman.spl &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1.7.2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 0AB91572-CACF-39DF-86B3-116FF8CDCB8E &amp;lt;69 7 5 4 3 1&amp;gt;
71    1 0xffffff7f828b0000 0x2d2000   0x2d2000   net.lundman.zfs &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1.7.2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 0F708776-FDC2-39C5-87CE-42CFF3C5DD48 &amp;lt;70 25 7 5 4 3 1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;tooling&quot;&gt;Tooling&lt;/h1&gt;

&lt;p&gt;ZFS has some pretty amazing tooling in the &lt;code class=&quot;highlighter-rouge&quot;&gt;zfs&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;zpool&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;zdb&lt;/code&gt; commands.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;zpool&lt;/code&gt; is used to create and manage pools of disks that logically present as a single
volume (like LVM), whereas &lt;code class=&quot;highlighter-rouge&quot;&gt;zfs&lt;/code&gt; is used to manage individual datasets, which are
nested hierarchically within pools but may have different tunings (recordsize, etc).&lt;/p&gt;

&lt;p&gt;One feature I found myself using a lot for monitoring was &lt;code class=&quot;highlighter-rouge&quot;&gt;zpool iostat&lt;/code&gt;, which gives
a current picture of I/O operations across the different media in the pool:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zpool iostat &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; 3
                                                  capacity     operations     bandwidth 
pool                                            alloc   free   &lt;span class=&quot;nb&quot;&gt;read  &lt;/span&gt;write   &lt;span class=&quot;nb&quot;&gt;read  &lt;/span&gt;write
&lt;span class=&quot;nt&quot;&gt;----------------------------------------------&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;
pool0                                            408G  10.5T    399    202  8.76M  13.2M
  raidz1                                         408G  10.5T    399    202  8.76M  13.2M
    media-4381EF74-91A2-A841-9073-00DD77A83EAA      -      -    133     70  2.92M  4.39M
    media-A00A5F1E-98B4-AA4C-ABE6-D19D52451730      -      -    133     69  2.92M  4.39M
    media-3D6C5673-A976-544C-9206-31ED6F4986E4      -      -    133     62  2.92M  4.40M
logs                                                -      -      -      -      -      -
  media-F0A2BB1A-583A-4D31-A9FD-887C7B326862     260K  7.00G      0      0      5     11
cache                                               -      -      -      -      -      -
  media-599EF695-4A06-488E-8679-FA03ED260C8D     519M  92.3G      0      0      1  7.16K
&lt;span class=&quot;nt&quot;&gt;----------------------------------------------&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;  &lt;span class=&quot;nt&quot;&gt;-----&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;/h2&gt;

&lt;p&gt;After installation, I made a pool of my three drives using the &lt;code class=&quot;highlighter-rouge&quot;&gt;zpool&lt;/code&gt; command:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zpool create pool0 raidz disk1 disk2 disk3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;striped-mirrored-or-raid-z&quot;&gt;Striped, mirrored, or RAID-Z?&lt;/h3&gt;

&lt;p&gt;You may be familiar with the different RAID levels (RAID0, RAID1, etc). Striping in ZFS
corresponds to RAID0, mirroring to RAID1, RAIDZ-1 to RAID5, and RAIDZ-2 to RAID6.&lt;/p&gt;

&lt;p&gt;These different setups offer different tradeoffs in:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Performance (IOPS)&lt;/li&gt;
  &lt;li&gt;Performance (bandwidth)&lt;/li&gt;
  &lt;li&gt;Space efficiency&lt;/li&gt;
  &lt;li&gt;Resiliency to drive failure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, striping the disks in parallel offers the best performance, since all disks
may be used independently in parallel. However, in this configuration the failure of
any one disk renders then entire set unusable, since it will contain a 1/N of the data.&lt;/p&gt;

&lt;p&gt;There are many in-depth looks at these different configurations, and even &lt;a href=&quot;http://www.raid-calculator.com&quot;&gt;calculators&lt;/a&gt;,
but it’s outside the scope of this article. Suffice to say, because it is my home computer
and I am somewhat stingy / out of available drive bays, I chose RAIDZ-1 for my configuration
of 3 x 4TB drives, resulting in ~8 TB of usable space while being able to tolerate failure
of any one drive.&lt;/p&gt;

&lt;p&gt;RAIDZ carries some notable performance limitations, however, these can be mitigated somewhat
by using an SSD for both write-ahead logging and caching (i.e. by using the SSD for better
low-latency random I/O). Since I have an SSD in my desktop as the main root device,
I created a small 8GB partition to use for write-ahead logging (the so-called ZIL, or ZFS intent log;
when split out onto an SSD sometimes referred to as an SLOG), and a medium-sized 100G partition
to use as a cache. These were added to the pool with:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zpool add pool0 cache disk4s1
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;zpool add pool0 log disk4s2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;tuning-for-mysql&quot;&gt;Tuning for MySQL&lt;/h3&gt;

&lt;p&gt;My computer runs a somewhat large MySQL instance (~3TB data), and MySQL on ZFS is not a
good match with the out-of-the-box default configuration. The main reasons for this are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;em&gt;Mismatched page size&lt;/em&gt;: ZFS and MySQL both manage data in fixed-size pages, however, the default
MySQL page size is 16K while the default ZFS page (called &lt;code class=&quot;highlighter-rouge&quot;&gt;recordsize&lt;/code&gt;) is 128K. This leads to thrashing
as updates to MySQL pages require read-modify-writes of the larger ZFS pages.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Redundancy&lt;/em&gt;: Both ZFS and MySQL perform write-ahead logging, checksumming, and optionally
compression of their data, which is redundant in this case.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Percona has a &lt;a href=&quot;https://www.percona.com/blog/2017/12/07/hands-look-zfs-with-mysql/&quot;&gt;great guide&lt;/a&gt;
on how to tune ZFS+MySQL to play nicely together, and there are some additional notes on the
&lt;a href=&quot;http://open-zfs.org/wiki/Performance_tuning#MySQL&quot;&gt;OpenZFS Wiki&lt;/a&gt;. In the end, for my setup,
I went with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Two separate ZFS datasets &lt;code class=&quot;highlighter-rouge&quot;&gt;mysql/data&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;mysql/logs&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;For the &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;recordsize=64k&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;compression=lz4&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;primarycache=metadata&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;logbias=throughput&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;For the &lt;code class=&quot;highlighter-rouge&quot;&gt;logs&lt;/code&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;recordsize=128k&lt;/code&gt; (the default)&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;primarycache=metadata&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;MySQL tunings:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;innodb_page_size=64k&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;skip-log-bin&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;innodb_doublewrite=off&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;innodb_checksum_algorithm=none&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these settings, we match the page size of MySQL to the recordsize of ZFS, and also
disable some of the redundant consistency settings in MySQL (double-writing and checksumming)
that are not strictly necessary since they are provided by ZFS.&lt;/p&gt;

&lt;p&gt;In addition, because both MySQL and ZFS perform in-memory caching, I limited the
size of ZFS’s in-memory (ARC) cache to 4GB and disabled data caching (&lt;code class=&quot;highlighter-rouge&quot;&gt;primarycache=metadata&lt;/code&gt;)
in favor of MySQL’s &lt;code class=&quot;highlighter-rouge&quot;&gt;innodb_buffer_pool&lt;/code&gt;, which is
&lt;a href=&quot;http://assets.en.oreilly.com/1/event/21/Optimizing%20MySQL%20Performance%20with%20ZFS%20Presentation.pdf&quot;&gt;reported to be 7-200% faster&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;memory-leak&quot;&gt;Memory leak?&lt;/h1&gt;

&lt;p&gt;The biggest issue I ran into was importing my large MySQL dataset. It seemed that
ZFS was leaking memory (in Activity Monitor a ballooning &lt;code class=&quot;highlighter-rouge&quot;&gt;kernel_task&lt;/code&gt;), even when
I limited the size of the in memory &lt;code class=&quot;highlighter-rouge&quot;&gt;ARC&lt;/code&gt; cache with &lt;code class=&quot;highlighter-rouge&quot;&gt;kstat.zfs.darwin.tunable.zfs_arc_max&lt;/code&gt;.
This would eventually degrade performance as both MySQL and ZFS would compete for
available memory.&lt;/p&gt;

&lt;p&gt;Thankfully, I eventually stumbled on a link to a &lt;a href=&quot;https://github.com/openzfsonosx/spl/issues/12&quot;&gt;Github issue&lt;/a&gt;
with the following helpful configuration snippet:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; kstat.zfs.darwin.tunable.zfs_arc_max&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;4294967296
sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; kstat.zfs.darwin.tunable.zfs_arc_meta_limit&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3221225472

sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; kstat.zfs.darwin.tunable.zfs_arc_min&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1610612736
sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; kstat.zfs.darwin.tunable.zfs_arc_meta_min&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1342177280
sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; kstat.zfs.darwin.tunable.zfs_dirty_data_max&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;536870912
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Apparently, when under intense write load (as when I was importing my MySQL dataset),
the memory allocator in SPL can fail to release dirty pages promptly, leading to what appears
to be a memory leak.&lt;/p&gt;

&lt;p&gt;After applying these sysctls (and making them persistent by adding them to &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/zfs/zsysctl.conf&lt;/code&gt;),
the memory usage seems to be appropriately capped.&lt;/p&gt;

&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h1&gt;

&lt;p&gt;While ZFS on macOS is definitely still a bit edge, I found it reasonably reliable, with no
observed kernel panics or other major issues. Performance definitely takes a hit, although the authors
claim that it may improve in time: to date they have primarily focused on stability rather than
performance (which seems wise given some of the backlash to early bugs in Btrfs). In addition,
ZFS offers a RAID5-like configuration not otherwise available in macOS. I’ll be curious to
see how it performs going forward, and whether or not any issues arise. I’m also interested
in setting up a system to use ZFS snapshots to perform incremental backups offsite.&lt;/p&gt;

&lt;p&gt;If you’re interested in diving into more technical details of ZFS, Chris Siebenmann has
an excellent series of &lt;a href=&quot;https://utcc.utoronto.ca/~cks/space/blog/solaris/ZFSRecordsizeAndCompression&quot;&gt;blogs about it&lt;/a&gt;.&lt;/p&gt;</content><author><name>Timothy Palpant</name><email>tim@palpant.us</email></author><summary type="html">ZFS is a filesystem developed at Sun Microsystems for their Solaris operating system. This is an experience report from recently setting it up as the filesystem for my secondary storage drives on macOS.</summary></entry><entry><title type="html">‘Advanced Format’ Disks</title><link href="https://tim.palpant.us/sysadmin/storage/2018/09/01/advanced-format/" rel="alternate" type="text/html" title="'Advanced Format' Disks" /><published>2018-09-01T22:29:45-05:00</published><updated>2018-09-01T22:29:45-05:00</updated><id>https://tim.palpant.us/sysadmin/storage/2018/09/01/advanced-format</id><content type="html" xml:base="https://tim.palpant.us/sysadmin/storage/2018/09/01/advanced-format/">&lt;p&gt;Last week, one of the drives in my desktop was having an unrecoverable read error, so I wanted to swap it out with another disk.
I had a Samsung 4TB external USB drive lying around, so I &lt;a href=&quot;https://www.urtech.ca/2018/03/solved-video-how-to-disassemble-a-seagate-backup-plus-external-disk-chassis/&quot;&gt;popped it out of its case&lt;/a&gt;
to put in the machine, and put the old drive (which still had some accessible data on it) in the USB enclosure.
After plugging it into my laptop, the partitions appeared to be corrupted:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/advanced-format/error.png&quot; alt=&quot;Unreadable&quot; /&gt;&lt;/p&gt;

&lt;p&gt;However, if I put the drive back in the desktop computer it seemed to be fine 🤔.&lt;/p&gt;

&lt;p&gt;On the desktop, Disk Utility reports a 512-byte block size:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;diskutil info /dev/disk1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Size:&quot;&lt;/span&gt;
Disk Size:                4.0 TB &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;4000787030016 Bytes&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;exactly 7814037168 512-Byte-Units&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Device Block Size:        512 Bytes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;whereas it is clear that an empty file takes up 4K:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;touch&lt;/span&gt; /Volumes/HD2/test.txt
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;stat&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;%k&quot;&lt;/span&gt; /Volumes/HD2/test.txt
4096
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;digging-deeper&quot;&gt;Digging Deeper&lt;/h1&gt;

&lt;p&gt;A few years ago, as drives began to surpass 2TB, hard drives upgraded their sector size from the historical
default of 512 bytes to &lt;a href=&quot;https://en.wikipedia.org/wiki/Advanced_Format&quot;&gt;Advanced Format&lt;/a&gt;, typically 4KB.
It seems there are varying approaches to how this is exposed however.&lt;/p&gt;

&lt;p&gt;Because many computers at the time assumed 512-byte sectors, some manufacturers exposed a 512-byte
sector to controllers, even though the disk actually used 4K sectors. Some didn’t, which can
lead to partition misalignment if the disk is moved to a different controller.
Others have run into this &lt;a href=&quot;https://apple.stackexchange.com/questions/202018/how-to-fix-guid-hard-drive-corrupted-to-mbr?rq=1&quot;&gt;problem&lt;/a&gt;
&lt;a href=&quot;https://apple.stackexchange.com/questions/182806/external-hdd-cannot-be-mounted&quot;&gt;too&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Cracking open a hex editor to look at the drive, it became apparent that the partition
header for HFS was not aligned to one of the 4k blocks:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/posts/advanced-format/hex.png&quot; alt=&quot;Misaligned Partition Map&quot; /&gt;
Source: &lt;a href=&quot;https://apple.stackexchange.com/questions/202018/how-to-fix-guid-hard-drive-corrupted-to-mbr?rq=1&quot;&gt;@klanomath’s great answer on StackExchange&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It seems like the drive was being addressed in the desktop as a 512-byte disk, whereas
the USB controller only supports 4K. So when plugging the USB drive into my laptop, the OS
searches for partitions but fails to find them because they are not aligned to 4K blocks.&lt;/p&gt;

&lt;h1 id=&quot;recovery&quot;&gt;Recovery&lt;/h1&gt;

&lt;p&gt;The simplest way to fix the partition map in this scenario is just to
&lt;a href=&quot;https://apple.stackexchange.com/questions/188844/change-drive-block-size-to-4096?noredirect=1&quot;&gt;reformat the drive&lt;/a&gt;
with Disk Utility, which will create a new partition table aligned to the appropriate
block size.&lt;/p&gt;

&lt;p&gt;After first making a full image of the drive in my desktop, I set out to see whether
I could recover the partitions without needing to fully reformat and re-image the drive,
which would take some time over USB. Thankfully, it was pretty easy to do with &lt;a href=&quot;https://www.cgsecurity.org/wiki/TestDisk&quot;&gt;TestDisk&lt;/a&gt;,
a utility for repairing partition tables.&lt;/p&gt;

&lt;p&gt;TestDisk was able to find the partition header for the single HFS+ partition on the drive,
and rewrite the partition table with the appropriate offsets. Thankfully, since the drive
had only one partition, it was pretty easy to find and fix. I’ll probably keep the backup
image around for a little while just in case.&lt;/p&gt;</content><author><name>Timothy Palpant</name><email>tim@palpant.us</email></author><summary type="html">Last week, one of the drives in my desktop was having an unrecoverable read error, so I wanted to swap it out with another disk. I had a Samsung 4TB external USB drive lying around, so I popped it out of its case to put in the machine, and put the old drive (which still had some accessible data on it) in the USB enclosure. After plugging it into my laptop, the partitions appeared to be corrupted:</summary></entry></feed>