Changing a ZVOL block size while making it sparse and compressed
Ryan Babchishin - 2016-10-17
If you use ZFS with zvols, you may have discovered they can be slow. This can often be blamed on the volblocksize attribute, which is read-only after zvol creation. The default value on Linux is 8k and I've read that performance is best at 128k (specifically for Linux systems). On my pool, it is definitely faster to set this value to 128k. There are benchmarks out there showing the differences like this one: https://github.com/zfsonlinux/zfs/issues/824. Another positive factor in performance can be compression. I always enable lz4, which works quite well for me.
Changing the block size requires that you create a new zvol and copy the old one onto it. Tough there are different ways, I find this way preferable. As part of the process, you can zero out the free space on the original zvol and write it using dd as sparse to the new zvol with compression enabled. Think about it. You'll reclaim all the free space on the zvol, get a faster block size and compress the whole thing. Speed and free space.
The steps
Do a backup
If the zvol is important to you, back it up.
Mount the existing zvol's partitions that contain file systems and write free space with zeros
mount /dev/zvol/pool2/myvol_root-part1 /mnt
cd /mnt
dd if=/dev/zero of=allzeros.dat bs=1M
rm allzeros.dat
cd /
umount /mnt
Rename the zvol
zfs rename pool2/myvol_root pool2/myvol_root_20161014
Create a new zvol of the same size as the old one with new parameters, especially volblocksize=128k and I suggest compression=lz4
zfs create -V 64G -o compression=lz4 -o volblocksize=128k pool2/myvol_root
Write the old zvol to the new one with dd's conv=sparse option
dd conv=sparse if=/dev/zvol/pool2/myvol_root_20161014 of=/dev/zvol/pool2/myvol_root bs=1M status=progress
Check out your free space
zfs list pool2/myvol_root
NAME USED AVAIL REFER MOUNTPOINT
pool2/myvol_root 66.0G 1.74T 4.36G -