Creating a ZFS pool in a Sparseimage or DMG on OS X

Since I see regular corruption and filesystem errors on my HFS+ partitions it seemed time to give ZFS on OS X a try.

Since there are several ZFS implementations for OS X available you can choose the one you feel most confident that will work. Regardless… here is the script I wrote to automate the creation of my zpools with some data safety against bit rot and filesystem corruption (at least more than HFS+ offers).

ZFS Utils for OS X
ZFS Utils for OS X on PyPI

You can install it like this:
[bash]pip install zfs-utils-osx
# Or if you don’t have pip available
easy_install zfs-utils-osx
[/bash]

Usage:
[bash]
# zfs.py -h
usage: zfs.py [-h] {zpool} …

optional arguments:
-h, –help show this help message and exit

Subcommands:
Please specify one of the following subcommands

{zpool}
zpool zpool creation
[/bash]

Zpool create usage:
[bash]
usage: zfs.py zpool [-h] [-c COUNT] [-s SIZE]
[-t {raidz1,raidz2,raidz3,mirror,raidz}] [-n]
[-m MOUNTPOINT] [-o] [-p PATTERN]
pool_name

positional arguments:
pool_name The name of the pool to create

optional arguments:
-h, –help show this help message and exit
-c COUNT, –count COUNT
The amount of images to use (default: 3)
-s SIZE, –size SIZE The usable size of the zpool in GiB (default: 10GiB)
-t {raidz1,raidz2,raidz3,mirror,raidz}, –type {raidz1,raidz2,raidz3,mirror,raidz}
The zpool type to use (default: raidz)
-n, –no-op, –dry-run
Show what will be done but dont execute
-m MOUNTPOINT, –mountpoint MOUNTPOINT
Where should the disk be mounted (default:
~/%(pool_name)s
-o, –overwrite Overwrite old images if they exist
-p PATTERN, –pattern PATTERN
File name pattern to store the images (default:
%(pool_name)s_%(i)02d)
[/bash]

And the actual creation of an image on my local system:
[bash]
# zfs.py zpool pool –count 4 –size 15
Creating 4 images named pool_00 of size 5.000000GiB for an effective
size of 15.000000GiB. The disk space used will be 20.000000GiB.
# hdiutil create -size 5g -volname pool_00 -type SPARSE -layout NONE pool_00
# hdiutil attach -nomount pool_00.sparseimage
# hdiutil create -size 5g -volname pool_01 -type SPARSE -layout NONE pool_01
# hdiutil attach -nomount pool_01.sparseimage
# hdiutil create -size 5g -volname pool_02 -type SPARSE -layout NONE pool_02
# hdiutil attach -nomount pool_02.sparseimage
# hdiutil create -size 5g -volname pool_03 -type SPARSE -layout NONE pool_03
# hdiutil attach -nomount pool_03.sparseimage
# sudo zpool create -f -m ~/pool pool raidz /dev/disk14 /dev/disk15 /dev/disk16 /dev/disk17
[/bash]

Zpool import usage:
[bash]
usage: zfs.py load [-h] [-d IMAGE_DIRECTORY] [-p PREFIX] [–postfix POSTFIX]
[-n]
pool_names [pool_names …]

positional arguments:
pool_names The name of the pool to import

optional arguments:
-h, –help show this help message and exit
-d IMAGE_DIRECTORY, –image-directory IMAGE_DIRECTORY
File name pattern to store the images (default:
~/zfs/)
-p PREFIX, –prefix PREFIX
File name prefix for the images (default:
%(pool_name)s_)
–postfix POSTFIX File name postfix for the images (default: )
-n, –no-op, –dry-run
Show what will be done but dont execute
[/bash]

Example run:
[bash]
# zfs.py load pool
# hdiutil attach -nomount /Users/rick/zfs/pool_00.sparseimage
# hdiutil attach -nomount /Users/rick/zfs/pool_01.sparseimage
# hdiutil attach -nomount /Users/rick/zfs/pool_02.sparseimage
# hdiutil attach -nomount /Users/rick/zfs/pool_03.sparseimage
# sudo zpool import pool[/bash]

And to make it mount automatically during boot (make sure you have sudo zpool in your sudoers file as passwordless), add this to /Library/LaunchDaemons/wolph.zfs.plist.

[xml]< ?xml version="1.0" encoding="UTF-8"?>
< !DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
Label
wolph.zfs
ProgramArguments

zfs.py
load
pool

RunAtLoad
[/xml]

In addition, if you want to speed it up a little with a ram drive. You can create and attach one like this:

The size is decided by the number after ram://, simply multiply the amount of megabytes you want by 2048 (in this case 4096 * 2048 = 4Gi of ram)
[bash]hdiutil attach -nomount ram://8388608
zpool add -f pool cache /dev/diskX[/bash]

The X should be replaced with the disk drive you got from the hdiutil command.

Note that using a ram drive as a cache drive is a _very_ bad idea if you have L1ARC available (i.e. all except the current OS X implementation I believe), in that case there is really no point to this as you will be trading really fast memory (L1ARC) for a slower ram drive which will be used slightly differently (L2ARC).

Bookmark and Share

About Rick van Hattem

Rick van Hattem is a Dutch Internet entrepreneur and co-founder of Fashiolista.com
No comments yet.

Leave a Reply