User Tools

Site Tools


Migrate non-ZFS root partition to ZFS



Identify current boot/root device:

df -h | egrep '\/$' | awk '{print $1}'

It must be something like da0p2.
Detect 'replacement' disk name:

geom disk list -a | grep name; ls /dev/*da*

Could be da1 for example.


Stop whatever running:

service apache24 stop
service mysql-server stop

Disable automatic start:

sysrc apache24_enable="NO"
sysrc mysql_enable="NO"

and so on.


New disk partitioning

Create new GPT layout on the new disk (assume it is da1):

gpart create -s gpt da1

Create 1st partition for bootloader, size 512k, align with 4k disk sector, label=boot1:

gpart add -s 1024 -a 4k -t freebsd-boot -l boot1 da1

Create 2nd partition for swap:

gpart add -s 4G -a 4k -t freebsd-swap -l swap da1

Create 3rd partition for ZFS:

gpart add -a 4k -t freebsd-zfs -l zroot da1

Verify the layout:

gpart show -lp da1

Install bootloader to the new disk, -i 1 means the first partition (labeled boot1):

gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da1

Set default block size for ZFS to 4k:

sysctl vfs.zfs.min_auto_ashift=12
echo 'vfs.zfs.min_auto_ashift=12' >> /etc/sysctl.conf


Create the new zpool:

zpool create -o altroot=/xmnt -O canmount=off -m none zroot /dev/gpt/zroot

altroot will be used for convenient mount of datasets
zroot is the new zpool name
/dev/gpt/zroot is label set up during partitioning
Ensure the pool is OK:

zpool status

Set datasets compression:

zfs set compression=lz4 zroot

Disable atime (access time modification) to prevent IO slowdown:

zfs set atime=off zroot


Create necessary datasets:

zfs create -o mountpoint=/ zroot/root
zfs create -o mountpoint=/tmp -o setuid=off zroot/tmp
zfs create -o mountpoint=/usr zroot/usr
zfs create -o mountpoint=/usr/home -o setuid=off zroot/usr/home
zfs create -o mountpoint=/usr/local zroot/usr/local
zfs create -o recordsize=8k -o mountpoint=/usr/local/pgsql zroot/usr/local/pgsql
zfs create -o mountpoint=/var zroot/var
zfs create -o mountpoint=/var/mail zroot/var/mail
zfs create -o mountpoint=/var/tmp zroot/var/tmp
zfs create -o mountpoint=/var/log zroot/var/log
zfs create -o mountpoint=/var/db zroot/var/db
zfs create -o recordsize=16k -o mountpoint=/var/db/mysql zroot/var/db/mysql


zfs list

Pay attention all the datasets are mounted to /xmnt/ instead of what was typed in.
Which dataset to be the root mountpoint:

zpool set bootfs=zroot/root zroot

Enable ZFS at boot:

echo 'zfs_enable="YES"' >> /etc/rc.conf
echo 'zfs_load="YES"' >> /boot/loader.conf

Copy data

Depending on current disk layout, copy separate filesystems to their new destinations:

cd / ; pax -p eme -X -rw . /xmnt
cd /var; pax -p eme -X -rw . /xmnt/var
cd /usr; pax -p eme -X -rw . /xmnt/usr

if the current system is installed as one partition, simply copy the root:

cd / ; pax -p eme -X -rw . /xmnt

That will copy all subdirectories (/usr, /var etc) to the appropriate datasets as they are mounted under /xmnt.


At this point all the data is at its place, bootloader is installed, zfs boot is enabled.
Either shutdown the system

halt -p

and remove the old drive to prevent it from being booted, or
reboot the system


and select proper boot device in BIOS/EFI.


Once the system is successfully booted, verify pool and filsystems:

zpool status
zfs list


If all OK, start your services one by one:

service mysql-server onestart
service apache24 onestart

and so on.
If all went fine, re-enable them with sysrc as it was done in Preparation section

ufs_to_zfs.txt · Last modified: 2020/08/03 14:13 by admin