A recent post to the Illumos ZFS list suggested using:

sysctl vfs.zfs.min_auto_ashift=12

to force ZFS to choose 4K disk blocks when creating zpools.

I checked with one of my stable/9 servers, running with ZFS at r270801, and lo and behold:

root@enterprise:~>sysctl -a | grep ashift
vfs.zfs.max_auto_ashift: 13
vfs.zfs.min_auto_ashift: 9

This is an ordinary sysctl which you can change at runtime:

root@enterprise:~>sysctl vfs.zfs.min_auto_ashift
vfs.zfs.min_auto_ashift: 9
root@enterprise:~>sysctl vfs.zfs.min_auto_ashift=12
vfs.zfs.min_auto_ashift: 9 -> 12
root@enterprise:~>

You should probably add this line to /etc/sysctl.conf, so that any future zpools created on your system are created with ashift=12:

vfs.zfs.min_auto_ashift=12

Setting this sysctl does not affect your system’s ability to import zpools created with ashift=9, nor does it magically transform your ashift=9 zpools to ashift=12 zpools.

I was able to verify this trick on stable/{9,10} and head. It sure beats dealing with gnop pseudo devices during zpool create.

Before knowing about vfs.zfs.min_auto_ashift, and its sibling, vfs.zfs.max_auto_ashift, I usually did this, using a mirrored zpool as an example:

kldload opensolaris
kldload zfs
hostname hostname.some.domain
gpart create -s gpt ada0
gpart create -s gpt ada1
gpart add -a 4K -s 512K -t freebsd-boot -l gptboot0 ada0
gpart add -a 4K -s 512K -t freebsd-boot -l gptboot1 ada1
gpart add -a 4K -s 4G -t freebsd-swap -l swap0 ada0
gpart add -a 4K -s 4G -t freebsd-swap -l swap1 ada1
gpart add -a 4K -t freebsd-zfs -l zroot0 ada0
gpart add -a 4K -t freebsd-zfs -l zroot1 ada1
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1
gnop create -S 4096 /dev/gpt/zroot0
gnop create -S 4096 /dev/gpt/zroot1
zpool create -o autoreplace=on -o cachefile=/tmp/zpool.cache -o failmode=continue -O mountpoint=legacy zroot mirror gpt/zroot0.nop gpt/zroot1.nop
zpool export zroot
gnop destroy /dev/gpt/zroot0.nop
gnop destroy /dev/gpt/zroot1.nop
zpool import -d /dev/gpt -o cachefile=/tmp/zpool.cache zroot

Contrast the above with:

kldload opensolaris
kldload zfs
sysctl vfs.zfs.min_auto_ashift=12
hostname hostname.some.domain
gpart create -s gpt ada0
gpart create -s gpt ada1
gpart add -a 4K -s 512K -t freebsd-boot -l gptboot0 ada0
gpart add -a 4K -s 512K -t freebsd-boot -l gptboot1 ada1
gpart add -a 4K -s 4G -t freebsd-swap -l swap0 ada0
gpart add -a 4K -s 4G -t freebsd-swap -l swap1 ada1
gpart add -a 4K -t freebsd-zfs -l zroot0 ada0
gpart add -a 4K -t freebsd-zfs -l zroot1 ada1
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1
zpool create -o autoreplace=on -o cachefile=/tmp/zpool.cache -o failmode=continue -O mountpoint=legacy zroot mirror gpt/zroot0 gpt/zroot1
zpool export zroot
zpool import -o cachefile=/tmp/zpool.cache zroot

ZFS statically compiled in the kernel

As of r233578, stable/10 and head can have the ZFS code statically compiled in the kernel.

include GENERIC
ident ZFS_FTW

options ZFS