A gotcha with importing ZFS pools and NFS exports on Linux (as of ZFS 2.3.0)
Ever since its Solaris origins, ZFS has supported automatic NFS and
CIFS sharing of ZFS filesystems through their 'sharenfs
' and
'sharesmb
' properties. Part of the idea of this is that you could
automatically have NFS (and SMB) shares created and removed as you
did things like import and export pools, rather than have to maintain
a separate set of export information and keep it in sync with what
ZFS filesystems were available. On Linux, OpenZFS still supports this, working
through standard Linux NFS export permissions (which don't
quite match the Solaris/Illumos model that's used for sharenfs
) and standard tools like exportfs. A lot
of this works more or less as you'd expect, but it turns out that
there's a potentially unpleasant surprise lurking in how 'zpool
import' and 'zpool export' work.
In the current code, if you import or export a ZFS pool that has
no filesystems with a sharenfs
set, ZFS will still run 'exportfs
-ra
' at the end of the operation even though nothing could have
changed in the NFS exports situation. An important effect that this
has is that it will wipe out any manually added or changed NFS
exports, reverting your NFS exports to
what is currently in /etc/exports and /etc/exports.d. In many
situations (including ours) this is a harmless operation, because
/etc/exports and /etc/exports.d are how things are supposed to be.
But in some environments you may have programs that maintain their
own exports list and permissions through running 'exportfs
' in
various ways, and in these environments a ZFS pool import or export
will destroy those exports.
(Apparently one such environment is high availability systems, some of which manually manage NFS exports outside of /etc/exports (I maintain that this is a perfectly sensible design decision). These are also the kind of environment that might routinely import or export pools, as HA pools move between hosts.)
The current OpenZFS code runs 'exportfs -ra' entirely blindly. It
doesn't matter if you don't NFS export any ZFS filesystems, much
less any from the pool that you're importing or exporting. As long
as an 'exportfs
' binary is on the system and can be executed, ZFS
will run it. Possibly this could be changed if someone was to submit
an OpenZFS bug report, but for a number of reasons (including that
we're not directly affected by this and aren't in a position to do
any testing), that someone will not be me.
(As far as I can tell this is the state of the code in all Linux OpenZFS versions up through the current development version and 2.3.0-rc4, the latest 2.3.0 release candidate.)
Appendix: Where this is in the current OpenZFS source code
The exportfs execution is done in nfs_commit_shares()
in
lib/libshare/os/linux/nfs.c.
This is called (indirectly) by sa_commit_shares()
in
lib/libshare/libshare.c,
which is called by zfs_commit_shares()
in lib/libzfs/libzfs_mount.c.
In turn this is called by zpool_enable_datasets()
and
zpool_disable_datasets()
, also in libzfs_mount.c, which
are called as part of 'zpool import' and 'zpool export' respectively.
(As a piece of trivia, zpool_disable_datasets() will also be called during 'zpool destroy'.)
|
|