🗂️ Aaron’s ZFS Guide – Table of Contents
I spent the previous week celebrating the Christmas holiday with family and friends, and as a result, took a break from blogging. However, other than the New Year, I’m finished with holidays for a while, and eager to get back to blogging, and finishing off this series. Only handful of posts left to go. So, let’s continue our discussion with ZFS administration on GNU/Linux, by discussing sharing datasets.
Disclaimer
I have been trying to keep these ZFS posts as operating system agnostic as much as possible. Even though they have had a slant towards Linux kernels, you should be able to take much of this to BSD or any of the Solaris derivatives, such as OpenIndiana or Nexenta. With this post, however, it’s going to be Linux-kernel specific, and even Ubuntu and Debian specific at that. The reason being is iSCSI support is not compiled into ZFS on Linux as of the writing of this post, but sharing via NFS and SMB is. Further, the implementation details for sharing via NFS and SMB will be specific to Debian and Ubuntu in this post. So, you may need to make adjustments if using Fedora, openSUSE, Gentoo, Arch, et cetera.
Motivation
You are probably asking why you would want to use ZFS specific sharing of datasets rather than using the “tried and true” methods with standard software. The reason is simple. When the system boots up, and goes through its service initialization process (typically by executing the shell scripts found in /etc/init.d/), it has a method to the madness on which service starts first. Loosely speaking, filesystems are mounted first, networking is enabled, then services are started at last. Some of these are tied together, such as NFS exports, which requires the filesystem to be mounted, a firewall in place, networking started, and the NFS daemon running. But, what happens when the filesystem is not mounted? If the directory is still accessible, it will be exported via NFS, and applications could begin dumping data into the export. This could lead to all sorts of issues, such as data inconsistencies. As such, administrators have put checks into place, such as exporting only nested directories in the mount point, which would not be available if the filesystem fails to mount. These are clever hacks, but certainly not elegant.
When tying the export directly into the filesystem, you can solve this beautifully, which ZFS does. In the case of ZFS, you can share a specific dataset via NFS, for example. However, if the dataset does not mount, then the export will not be available to the application, and the NFS client will block. Because the network share is inherent to the filesystem, there is no concern for data inconsistencies, and no need for silly check hacks or scripts. As a result, ZFS from Oracle has the ability to share a dataset via NFS, SMB (CIFS or Samba) and iSCSI. ZFS on Linux only supports NFS and SMB currently, with iSCSI support on the way.
In each case, you still must install the necessary daemon software to make the share available. For example, if you wish to share a dataset via NFS, then you need to install the NFS server software, and it must be running. Then, all you need to do is flip the sharing NFS switch on the dataset, and it will be immediately available.
Sharing via NFS
To share a dataset via NFS, you first need to make sure the NFS daemon is running. On Debian and Ubuntu, this is the “nfs-kernel-server” package. Further, with Debian and Ubuntu, the NFS daemon will not start unless there is an export in the /etc/exports file. So, you have two options: you can create a dummy export, only available to localhost, or you can edit the init script to start without checking for a current export. I prefer the former. Let’s get that setup:
$ sudo aptitude install -R nfs-kernel-server
$ echo '/mnt localhost(ro)' >> /etc/exports
$ sudo /etc/init.d/nfs-kernel-server start
$ showmount -e hostname.example.com
Export list for hostname.example.com:
/mnt localhost
With our NFS daemon running, we can now start sharing ZFS datasets. I’ll assume already that you have created your dataset, it’s mounted, and you’re ready to start committing data to it. You’ll notice in the zfs(8) manpage, that for the “sharenfs” property, it can be “on”, “off” or “opts”, where “opts” are valid NFS export options. So, if I wanted to share my “pool/srv” dataset, which is mounted to “/srv” to the 10.80.86.0/24 network, I could do something like:
# zfs set sharenfs="rw=@10.80.86.0/24" pool/srv
# zfs share pool/srv
# showmount -e hostname.example.com
Export list for hostname.example.com:
/srv 10.80.86.0/24
/mnt localhost
If you want your ZFS datasets to be shared on boot, then you need to install the /etc/default/zfs config file. If using the Ubuntu PPA, this will be installed by default for you. If compiling from source, this will not be provided. Here are the contents of that file. I’ve added emphasis to the two lines that should be modified for persistence across boots, if you want to enable sharing via NFS. Default is ‘no’:
$ cat /etc/default/zfs
# /etc/default/zfs
#
# Instead of changing these default ZFS options, Debian systems should install
# the zfs-mount package, and Ubuntu systems should install the zfs-mountall
# package. The debian-zfs and ubuntu-zfs metapackages ensure a correct system
# configuration.
#
# If the system runs parallel init jobs, like upstart or systemd, then the
# `zfs mount -a` command races in a way that causes sporadic mount failures.
# Automatically run `zfs mount -a` at system start. Disabled by default.
ZFS_MOUNT='yes'
ZFS_UNMOUNT='no'
# Automatically run `zfs share -a` at system start. Disabled by default.
# Requires nfsd and/or smbd. Incompletely implemented for Linux.
ZFS_SHARE='yes'
ZFS_UNSHARE='no'
As mentioned in the comments, running a parallel init system creates problems for ZFS. This is something I recently banged my head against, as my /var/log/ and /var/cache/ datasets were not mounting on boot. To fix the problem, and run a serialized boot, thus ensuring that everything gets executed in the proper order, you need to touch a file:
# touch /etc/init.d/.legacy-bootordering
This will add time to your bootup, but given the fact that my system is up months at a time, I’m not worried about the extra 5 seconds this puts on my boot. This is documented in the /etc/init.d/rc script, setting the “CONCURRENCY=none” variable.
You should now be able to mount the NFS export from an NFS client:
(client)# mount -t nfs hostname.example.com:/srv /mnt
Sharing via SMB
Currently, SMB integration is not working 100%. See bug #1170 I reported on Github. However, when things get working, this will likely be the way.
As with NFS, to share a ZFS dataset via SMB/CIFS, you need to have the daemon installed and running. Recently, the Samba development team released Samba version 4. This release gives the Free Software world a Free Software implementation of Active Directory running on GNU/Linux systems, SMB 2.1 file sharing support, clustered file servers, and much more. Currently, Debian testing has the beta 2 packages. Debian experimental has the stable release, and it may make its way up the chain for the next stable release. One can hope. Samba v4 is not needed to share ZFS datasets via SMB/CIFS, but it’s worth mentioning. We’ll stick with version 3 of the Samba packages, until version 4 stabilizes.
# aptitude install -R aptitude install samba samba-client samba-doc samba-tools samba-doc-pdf
# ps -ef | grep smb
root 22413 1 0 09:05 ? 00:00:00 /usr/sbin/smbd -D
root 22423 22413 0 09:05 ? 00:00:00 /usr/sbin/smbd -D
root 22451 21308 0 09:06 pts/1 00:00:00 grep smb
At this point, all we need to do is share the dataset, and verify that it’s been shared. It is also worth noting that Microsoft Windows machines are not case sensitive, as things are in Unix. As such, if you are in a heterogenious environment, it may be worth disabling case sensitivity on the ZFS dataset. Setting this value can only be done on creation time. So, you may wish to issue the following when creating that dataset:
# zfs create -o casesensitivity=mixed pool/srv
Now you can continue with configuring the rest of the dataset:
# zfs set sharesmb=on pool/srv
# zfs share pool/srv
# smbclient -U guest -N -L localhost
Domain=[WORKGROUP] OS=[Unix] Server=[Samba 3.6.6]
Sharename Type Comment
--------- ---- -------
print$ Disk Printer Drivers
sysvol Disk
netlogon Disk
IPC$ IPC IPC Service (eightyeight server)
Canon-imageRunner-3300 Printer Canon imageRunner 3300
HP-Color-LaserJet-3600 Printer HP Color LaserJet 3600
salesprinter Printer Canon ImageClass MF7460
pool_srv Disk Comment: /srv
Domain=[WORKGROUP] OS=[Unix] Server=[Samba 3.6.6]
Server Comment
--------- -------
EIGHTYEIGHT eightyeight server
Workgroup Master
--------- -------
WORKGROUP EIGHTYEIGHT
You can see that in this environment (my workstation hostname is ‘eightyeight’), there are some printers being shared, and a couple disks. I’ve emphasized the disk that we are sharing in my output, to verify that it is working correctly. So, we should be able to mount that share as a CIFS mount, and access the data:
# aptitude install -R cifs-utils
# mount -t cifs -o username=USERNAME //localhost/srv /mnt
# ls /mnt
foo
Sharing via iSCSI
Unfortunately, sharing ZFS datasets via iSCSI is not yet supported with ZFS on Linux. However, it is available in the Illumos source code upstream, and work is being done to get it working in GNU/Linux. As with SMB and NFS, you will need the iSCSI daemon installed and running. When support is enabled, I’ll finish writing up this post on demonstrating how you can access iSCSI targets that are ZFS datasets. In the meantime, you would do something like the following:
# aptitude install -R openiscsi
# zfs set shareiscsi=on pool/srv
At which point, from the iSCSI client, you would access the target, format it, mount it, and start working with the data…
This article includes content by Aaron Toponce, originally published on pthree.org in 2012, which is unfortunately no longer available online. I’ve mirrored his valuable work here to ensure that readers continue to have access to this information.