The goal of this project is to make Darwin more usable by providing an installation ISO, documentation, and add-on software. You are welcome to join #puredarwin on irc.freenode.net if you would like to join PureDarwin development and to add to this site.

Recent site activity

For the curious‎ > ‎

ZFS

ZFS stands for "Zettabyte File System". It was designed and implemented by a team at Sun Microsystems led by Jeff Bonwick. Support has been included in Darwin 9, but as of Snow Leopard, any mentions of ZFS have been removed by Apple. We hope to use more ZFS and its features in PureDarwin if possible.

Update: The Mac port of ZFS is no longer hosted on http://zfs.macosforge.org/ but the zfs-macos project is continuing to host the codebase. 


The ZFS implementation that runs on Mac OS X (and Darwin) can be downloaded or compiled.
See the ZFS page from Mac OS Forge. Keep also an eye on their Issue page.

Fyi, ZFS is pure.

Parts of ZFS

On Mac OS X (and Darwin), ZFS consists of the following parts:
  1. A filesystem kext, System/Library/Extensions/zfs.kext
    Whenever zfs is used, this kext gets loaded. Being a filesystem kext, it is not loaded at boot time (unlike other kexts), but dynamically when needed (this requires a working kextload on the system).
    There may also be a zfs.readonly.kext, which is a temporary placeholder on Mac OS X and is not needed for the purposes of PureDarwin.
  2. A filesystem, /System/Library/Filesystems/zfs.fs
    Contained therein is, among other things, a command-line tool called zfs.util
  3. A library, libzfs.dylib
  4. Command-line tools in /usr/sbin, 
    1. zpool (configures ZFS storage pools)
    2. zfs (configures ZFS file systems)
    3. zoink (misc)
    4. zfs.util (ZFS file system utility)
  5. A settings file, /etc/zfs/zpool.cache (a cache that describes active ZFS pools on the system)
  6. The device /dev/zfs, this is created automatically when zfs.kext gets loaded (which happens whenever you call the zfs command-line tool, for example).

Filesystem kext

As mentioned above, zfs.kext is not a regular kernel extension but instead is a filesystem kext. Among other things, this means that it is not loaded at boot time, but is loaded automatically on demand through kextload. Unfortunately, documentation on filesystem kexts is hard to find.

Examples

Typical scenario on Darwin

Here is an example of how to use ZFS to use a compressed disk image on a PureDarwin system.
The following is done on Darwin 9.5 with zfs-119 compiled with "Use Separate strip" workaround.
  1. Mount the root device read-write, e.g., using mount -uw /
  2. Optionally, do kextload /System/Library/Extensions/zfs.kext (this is done automatically when you call zfs, but it might be a good idea to call this manually for debugging purposes). The device /dev/zfs should now be present.
  3. Create a 64 MB disk image file (this is the minimum disk image size supported by ZFS) with
    dd if=/dev/zero of=/zfs.img bs=1024k count=64
  4. Create a ZFS pool from this image (this is roughly equivalent to formatting a disk image and mounting it):
    zpool create zfstest /zfs.img
  5. The filesystem should now be mounted at /Volumes/zfstest; verify that it is.
    You can also run zpool list to see the ZFS pools on your system. zfstest should be there.
  6. To enable compression, do
    zfs set compression=on zfstest
  7. To check the compression ratio, do
    zfs get compressratio
    (tests with some binaries gave compression ratios around 2x)
If you want to reboot, do zfs umount zfstest ; sync and if you want to mount again after you have rebooted all you have to do is mount -uw / ; fs mount zfstest. Note that ZFS has remembered (inside the img and cached in /etc/zfs/zpool.cache) the details about the `zfstest' pool (such as that /zfs.img is to be used and that the mountpoint is /Volumes/zfstest).

On Mac OS X

The following is done on Mac OS X (10.5.5) with zfs-119 compiled with "Use Separate strip" workaround.

zpool will fail with 256m, so take at least 512m for the image size.

hdiutil create -fs HFS+J -size 512m zfshadow
.................................................................
created: /Users/aladin/PureDarwin/zfshadow.dmg

Then attach the fresh image.

hdiutil attach zfshadow.dmg
/dev/disk1 GUID_partition_scheme
/dev/disk1s1 Apple_HFS /Volumes/untitled

Prepare the disk image, GPT is mandatory.

diskutil partitiondisk /dev/disk1 GPTFormat ZFS %noformat% 100%
Started partitioning on disk disk1
Creating partition map
[ + 0%..10%..20%..30%..40%..50%..60%..70%..80%..90%..100% ]
Finished partitioning on disk disk1
/dev/disk1
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme *512.0 Mi disk1
1: ZFS 512.0 Mi disk1s1

Create a pool.

zpool create PureDarwin /dev/disk1

Mount doesn't lie.

mount
/dev/disk0s2 on / (hfs, local, journaled)
devfs on /dev (devfs, local)
fdesc on /dev (fdesc, union)
map -hosts on /net (autofs, automounted)
map auto_home on /home (autofs, automounted)
PureDarwin on /Volumes/PureDarwin (zfs, local)

Neither does zpool.

zpool status
  pool: PureDarwin
 state: ONLINE
status: The pool is formatted using an older on-disk format.  The pool can
still be used, but some features are unavailable.
action: Upgrade the pool using 'zpool upgrade'.  Once this is done, the
pool will no longer be accessible on older software versions.
 scrub: none requested
config:

NAME        STATE     READ WRITE CKSUM
PureDarwin  ONLINE       0     0     0
 disk1     ONLINE       0     0     0

errors: No known data errors

Miscellaneous

`zoink' displays some statistics.

 ZFS footprint:    6M used,    6M peak,   96M goal                32 threads
 ARC footprint:    0M used,    0M peak,  682M goal

                        obj      slab    active     total      peak    total
 kmem_cache name       size      size      objs      objs      objs      mem
-----------------------------------------------------------------------------
 kmem_magazine_1          8      4096        77       508       508       3K
 kmem_magazine_3         16      4096       409       508       508       7K
 kmem_magazine_7         32      4096        26       127       127       3K
 kmem_magazine_15        64      4096         5        63        63       3K
 kmem_slab_cache         28      4096       175       254       254       6K
 kmem_bufctl_cache       12      4096      1511      1524      1524      17K
 taskq_ent_cache         48      4096       300       336       336      15K
 taskq_cache            204      4096        25        38        38       7K
 zfs_znode_cache        212     32768         0       151       151      31K
 zio_bufs 540           540      8192        33       653       653     276K
 zio_bufs 512           512     32768        33       192       192      64K
 zio_bufs 1024         1024     16384         2       544       544     528K
 zio_bufs 1536         1536     12288         0         8         8      12K
 zio_bufs 2048         2048      4096         0         4         4       8K
 zio_bufs 2560         2560     20480         0        16        16      20K
 zio_bufs 3072         3072     12288         0         8         8      12K
 zio_bufs 3584         3584     28672         0         8         8      28K
 zio_bufs 4096         4096      4096         6        14        14      32K
 zio_bufs 5120         5120     20480         0         4         4      20K
 zio_bufs 6144         6144     12288         0         2         2      12K
 zio_bufs 7168         7168     28672         0         4         4      28K
 zio_bufs 8192         8192      8192         0         6         6      32K
 zio_bufs 10240       10240     20480         0         4         4      20K
 zio_bufs 12288       12288     12288         0         2         2      24K
 zio_bufs 14336       14336     28672         0        12        12     168K
 zio_bufs 16384       16384     16384         6        17        17     272K
 zio_bufs 20480       20480     20480         0         2         2      20K
 zio_bufs 36864       36864     36864         0         3         3       0K
 zio_bufs 53248       53248     53248         0         3         3      52K
 zio_bufs 65536       65536     65536         4         6         6     256K
 zio_bufs 114688     114688    114688         0         4         4     448K
 zio_bufs 122880     122880    122880         0         3         3     360K
 zio_bufs 131072     131072    131072         2         5         5     640K
 dmu_buf_impl_t         184     32768        45       177       177      31K
 dnode_t                556      4096        36       112       112      60K
 arc_buf_hdr_t          172      8192       111       138       138      23K
 arc_buf_t               20      4096        31       169       169       3K
-----------------------------------------------------------------------------
 kmem_cache total:                           0M        4M

Performance, Integrity and Stability

Sun (and the FreeBSD project) recommend that at least 512MB of RAM is available, to ensure that ZFS performs reliably, although it will work on systems with less than 512MB with suboptimal performance. ZFS was designed to perform best on 64-bit systems, although it works on 32-bit systems.

Building zfs

Our favorite way is through darwinbuild via a custom plist containing the paste below. You will notice that only two architectures have been specified, because it does not yet build on 64bits arch (ppc64 or x86_64). `darwinbuild zfs' is pretty straight forward.
zfs = {
configuration = "Leopard_Release";
dependencies = {
lib = (
Libsystem,
dyld,
libgcc,
ncurses,
);
};
environment = {
"RC_ARCHS" = "i386 ppc";
};
"source_sites" = (
"http://puredarwin.googlecode.com/hg/Mirror/",
"http://puredarwin.googlecode.com/svn/Mirror/",
);
version = "119";
};

Resources