Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

What is this?

This is a C# program that reads ZFS file systems. Writing is explicitly a non-goal. Several types of disk images are supported: raw, VHD, VHDX, and VDI. RAIDZ, mirror, and stripe vdevs are supported.

Code Layout

  • ZfsSharpLib: A library for reading ZFS files.
  • ZfsProjFs: Mount a pool using Windows Projected Filesystem.
  • Austin.WindowsProjectedFileSystem: A library for using Windows Projected Filesystem. Not specific to ZFS.
  • ZfsDokan: Mount a pool using Dokan.
  • ZfsSharp: Mostly used for testing and benchmarking.

Future plans

  • Improve Windows Project Filesystem support. Currently it works mostly ok, but for some reason directory entries are duplicated.
  • Add support for FUSE.
  • Add async support to parrelleize checksumming and decompression.

What I'm learning

It was exciting to get enough code working so I could read the uberblock in disk label. However it was a long way from there to reading any information out of the pool as I had to implement decompression and checksumming. This made obvious how fundamentally data integrity is backed into ZFS.

The second moment of zen was to see the bock pointer's abstraction of 128k blocks of copy-on-write data being used by dnodes to create an abstraction of arbitrarily large pieces of data. By merely implementing the dnode and blkptr abstractions you get access to the fundamental data management tools of ZFS. Everything else in ZFS is just reading out of those.

I found it interesting that ZFS incorporates three different ways of storing key-value pairs: ZAP, XDR, and SA. Each system is designed for different performance profiles:

  • SA: compactly storing small amounts of data, where many objects use the same key
  • ZAP: fast lookup by key to handle large directories
  • XDR: Config data that is rarely read or written. Probably used because it was lying around in Solaris for NFS, so why create something new.

When I implemented the third system I started to get a feeling of Déjà vu.

What parts of ZFS I wish were better documented

During the creation of this I found the ZFS On-Disk Specification to be quite helpful. However it describes the initial version of zpool and zfs. OpenZFS is forked off OpenSolaris at zpool version 28 and zfs 5. Since then OpenZFS has added many features, so there are several aspects of the system that are lacking diagrams in the On-Disk Specification document. Eventually I'd like to make a blog post full of pretty pictures to describe these structures.

An example of outdated documentation in the On-Disk Specification is the znode_phys_t structure. In zfs v5 this was replaced with the system attribute (SA) system. The comment at the start of sa.c is pretty good so it was not difficult to figure out. I think a nice diagram would have made it even easier to understand.

The description of the Fat ZAP makes sense now that I've implemented it. However I remember it being somewhat obtuse while implementing it.

The best documentation on how XDR worked was looking at GRUB's code. Since it only needs to implement enough to boot the system, it quickly gets to the heart of the matter. So XDR could benefit from more documentation.


An experiment in reading ZFS in C#. CDDL licensed.






No releases published


No packages published