I'll start this post referring to the global zone, later I hope to touch non-global zones.
By default, ZFS creates /export below rpool as rpool/export.
rpool/export in turn has the following hierarchy:
- rpool/export/home
- rpool/export/home/<user>
The problem is:
I don't like this default, because I prefer a maximal decoupling from rpool.
It's typically a good idea for NFS servers to set /export on a larger device.
NOTE
I haven't heard about any issues by deviating from the default.Accomplishing the mission:
Don't forget to update the automounter info as well, as needed.
That may typically include /etc/auto_home, NIS or LDAP.
Enter single-user state (SINGLE USER MODE) by booting with the -s option.
Note that init S or s isn't enough to umount eventually busy file systems.
Enter single-user credentials (usually root or preferably a RABC configured login).
This will precisely let us play with rpool/export without any hassles.
rpool/VARSHARE is a new Solaris 11.1 feature to save space in boot environments.
<user> is an user typically configured with access to the root role.
# zfs list -r -d 3 -o name,mountpoint,mounted rpool
NAME MOUNTPOINT MOUNTED
rpool /rpool no
rpool/ROOT legacy no
rpool/ROOT/solaris / yes
rpool/ROOT/solaris-bk / no
rpool/ROOT/solaris-bk/var /var no
rpool/ROOT/solaris/var /var yes
rpool/VARSHARE /var/share yes
rpool/dump - -
rpool/export /export no
rpool/export/home /export/home no
rpool/export/home/<user> /export/home/<user> no
rpool/swap - -
Create and configure a new pool and name it export.
You may decide to enable compression, encryption, deduplication, and so on...
I'll omit many details on this step and assume the existence of such a new pool.
(# zpool create -O compression=on -O dedup=on export <device>)
For each hierarchy within the current /export subtree (for instance home):
Recursively snapshot it:
# zfs snapshot -r rpool/export/home@migrate
Replicate it via send/receive to the new pool:
# zfs send -R rpool/export/home@migrate \
| zfs recv -d -x mountpoint export
Delete it or at least disable it from automatically mounting:
# zfs set -r canmount=noauto rpool/export
Clean up snapshots used in the migration:
# zfs destroy -r rpool/export/home@migrate
# zfs destroy -r export/home@migrate
NOTE
The above snapshot-releated commands could be simplified:Finally, our result is as follows:
(the -F option overwrites anything in the new export pool, "empty" anyway)
# zfs snapshot -r rpool/export@migrate
# zfs send -R rpol/export@migrate |zfs recv -F export
# zfs destroy -r rpool/export
# zfs destroy -r export@migrate
# zfs list -r -o name,mountpoint,mounted export
NAME MOUNTPOINT MOUNTED
export /export no
export/home /export/home no
export/home/<user> /export/home/<user> no
For the non-global zones things vary depending on the system version.
The /export is only present by default from Solaris 11 upwards.
In fact on newer systems, the default file systems are:
# zfs list
NAME USED AVAIL REFER MOUNTPOINT
rpool 446M 252G 31K /rpool
rpool/ROOT 446M 252G 31K legacy
rpool/ROOT/solaris 446M 252G 414M /
rpool/ROOT/solaris/var 29.7M 252G 29.0M /var
rpool/VARSHARE 39K 252G 39K /var/share
rpool/export 96.5K 252G 32K /export
rpool/export/home 64.5K 252G 32K /export/home
rpool/export/home/<user> 32.5K 252G 32.5K /export/home/<user>
This is the view from within a non-global zone <ngz>.
That's quite cool as it closely resembles a physical system.
As such, rpool/swap and rpool/dump aren't present, of course.
Assume a dedicated pool zone for zones.
From the global zone perspective, the non-global zone file system hierarchy is:
# zfs list -r -o name,mountpoint zone
NAME MOUNTPOINT
zone /zone
zone/<ngz> /zone/<ngz>
zone/<ngz>/rpool /rpool
zone/<ngz>/rpool/ROOT legacy
zone/<ngz>/rpool/ROOT/solaris /zone/<ngz>/root
zone/<ngz>/rpool/ROOT/solaris/var /zone/<ngz>/root/var
zone/<ngz>/rpool/VARSHARE /zone/<ngz>/root/var/share
zone/<ngz>/rpool/export /export
zone/<ngz>/rpool/export/home /export/home
zone/<ngz>/rpool/export/home/<user> /export/home/<user>
Decoupling /export as was proposed for the global zone is just slightly different.
NOTE
It's crucial that the new dataset be independent of the zone's datasets hierarchy. I mean that it shouldn't be a descendand of the zone/<ngz> pool as per the above example, otherwise non-global zone machinery may get broken.There are many possibilities where to locate the non-global zone's export dataset.
For instance, among others, we could choose one of the following options:
- Use new individual pools for each non-global zones' export dataset
- Use a new single pool for all non-global zones' export dataset
- Use an already existent export pool for the global zone
- Use an already existent zone pool for the zones
Which approach to follow, depends on a variety of reasons.
If a zone makes heavy usage of /export, then a dedicated pool might be better.
Otherwise, it could certainly share a pool with other such zones.
But note that too many pools may lead to inefficient storage utilization.
For Solaris 11 onwards things are even easier due to dataset aliasing.
Let's see each of these possibilities, in turn, starting by Solaris 11.
SOLARIS 11
Just for example, assume that <ngz> is in zone, that is, zone/<ngz>
The scenario is excatly the one described above for a non-global zone.
Here's an strategy:
- Create an appropriate dataset to host the new /export hierarchy
- Assign it to the zone configuration, aliasing it to export.
- Boot in single-user mode and migrate data
# zfs create -o zoned=on -o mountpoint=/export zone/<ngz>-export
# zonecfg -z <ngz>
zonecfg:<ngz>> add dataset
zonecfg:<ngz>:dataset> set name=zone/<ngz>-export
zonecfg:<ngz>:dataset> set alias=export
zonecfg:<ngz>:dataset> end
zonecfg:<ngz>> verify
zonecfg:<ngz>> commit
zonecfg:<ngz>> exit
# zoneadm -z <ngz> boot -s
# zlogin -C <ngz>
[NOTICE: Zone booting up with arguments: -s]
SunOS Release 5.11 Version 11.1 64-bit
Copyright (c) 1983, 2012, Oracle ... All rights reserved.
Booting to milestone "milestone/single-user:default".
Hostname: <ngz>
Requesting System Maintenance Mode
SINGLE USER MODE
Enter user name for system maintenance (...): root
Enter root password (...): ************
Apr 29 13:05:07 su: 'su root' succeed for root on /dev/console
root@<ngz>:~# zfs list -r -o name,mountpoint,mounted,canmount
NAME MOUNTPOINT MOUNTED CANMOUNT
export /export no on
rpool /rpool no on
rpool/ROOT legacy no off
rpool/ROOT/solaris / yes noauto
rpool/ROOT/solaris/var /var yes noauto
rpool/VARSHARE /var/share yes noauto
rpool/export /export no on
rpool/export/home /export/home no on
rpool/export/home/<user> /export/home/<user> no on
root@<ngz>:~# zfs snapshot -r rpool/export/home@migrate
root@<ngz>:~# zfs send -R rpool/export/home@migrate |
zfs recv -e -x mountpoint export
root@<ngz>:~# zfs list -r -o name,mountpoint,mounted,canmount
NAME MOUNTPOINT MOUNTED CANMOUNT
export /export yes on
export/home /export/home yes on
export/home/<user> /export/home/<user> yes on
rpool /rpool no on
rpool/ROOT legacy no off
rpool/ROOT/solaris / yes noauto
rpool/ROOT/solaris/var /var yes noauto
rpool/VARSHARE /var/share yes noauto
rpool/export /export no on
rpool/export/home /export/home no on
rpool/export/home/<user> /export/home/<user> no on
root@<ngz>:~# zfs set -r canmount=noauto rpool/export
root@<ngz>:~# zfs destroy -r rpool/export/home@migrate
root@<ngz>:~# zfs destroy -r export/home@migrate
root@<ngz>:~# reboot
LEGACY
In legacy systems, such as Solaris 11 Express, dataset aliasing isn't available.
In this case, I'd propose using an export pool for a more consistent naming.
Most steps are the same so I won't repeat them, showing only the outline.
From the global zone, it would be seen as in the following arrangement:
# zfs list -r -o name,mountpoint export
NAME MOUNTPOINT
export /export
export/home /export/home
export/home/<user> /export/home/<user>
export/<ngz> /export/<ngz>
export/<ngz>/home /export/<ngz>/home
export/<ngz>/home/<user> /export/<ngz>/home/<user>
# zonecfg -z <ngz> info dataset
dataset:
name: export/<ngz>
From a legacy non-global zone (without aliasing) the arrangement would be seen as:
# zlogin -l <user> <ngz>
[Connected to zone '<ngz>' pts/2]
<user>@<ngz>:~# zfs list -o name,mountpoint
NAME MOUNTPOINT
export /export
export/<ngz> /export/<ngz>
export/<ngz>/home /export/<ngz>/home
export/<ngz>/home/<user> /export/<ngz>/home/<user>
zone /zone
zone/<ngz> /zone/<ngz>
zone/<ngz>/ROOT legacy
zone/<ngz>/ROOT/zbe legacy
<user>@<ngz>:~# tail /etc/auto_home
...
#
+auto_home
#
* localhost:/export/<ngz>/home/&
Naturally, this will imply that the user info must be updated accordingly.
# usermod -d /home/<user> <user>