A terminal UI and scripting front-end for ZFS pool properties — zpool get /
zpool set — for FreeBSD. Sibling of zfs-set
(dataset properties), zfs-allow and
facl, same look and feel.
zpool-set lists every property of a pool with its value and source, explains
each one (zpoolprops(7)) and each feature (zpool-features(7)), edits them
through a list of the allowed values with their meaning or a validated text
field, and shows the exact zpool set commands before running them — with
pre-flight notes for what zpool will refuse and what the change implies.
go install github.com/olgeni/zpool-set@latest
or git clone … && go build. The man page is zpool-set.1; shell completions
for zsh, bash and fish are in completions/.
zpool-set [pool]
Without a pool a picker lists the imported pools (size, allocated, free, capacity, fragmentation, health), with the pool of the current directory preselected.
Main screen: the properties by group — behaviour (autoexpand,
autoreplace, autotrim, delegation, failmode, listsnapshots,
multihost), configuration (bootfs, cachefile, comment,
compatibility, ashift, version, dedup_table_quota), the import-time
ones (altroot, readonly: shown, not editable), the features (disabled /
enabled / active), the read-only statistics and the user properties —
each with its value and source; the meaning of the selected property is
explained at the bottom. Pending edits show as
→ value until you apply.
| key | |
|---|---|
| enter, e | edit: set a value, or reset to the default; on a feature: enable it |
| c | reset to the default (user property: remove), pending |
| a | add a user property (module:name) |
| d | drop the pending edit of the property |
| A | apply: preview the commands and pre-flight notes, then run them |
| u / r | undo · reload |
| / | filter by name or meaning · l only the properties set on the pool · f hide/show the features |
| v | the vdev tree; enter on a vdev opens its properties (below) |
| m | mouse on/off: click a row to select it, click again to open it, wheel scrolls |
| D | switch pool |
| ? / h | help / keys |
Vdevs: v shows the tree of the pool — the root, the top-level vdevs and
their leaves, with type, state, size, allocation, errors, ashift and comment
— and enter opens the properties of one vdev (vdevprops(7)): the fault
thresholds zfsd/zed act on (checksum_n/checksum_t, io_n/io_t,
slow_io_n/slow_io_t, slow_io_events), failfast, allocating,
sit_out/autosit on raidz/draid, comment, path, the read-only
statistics and the vdev's own user properties, with the same editor. Edits on
the pool and on any number of vdevs are applied together (zpool set io_n=10 tank mirror-0); the tree marks the vdevs with pending edits.
Editor: set a value — a radio list of every allowed value with its meaning
(failmode, ashift, the on/off ones), a filterable picker for
compatibility (every file of /usr/share/zfs/compatibility.d), or a
validated text field (bootfs, cachefile, comment, dedup_table_quota)
— or reset. enter on a value selects it and confirms.
The plan screen lists one zpool set command per edit, the resulting values,
and the pre-flight notes:
- what zpool will refuse:
altroot/readonly(import time only), a feature that does not exist here or that you try to disable, abootfsoutside the pool or that does not exist,multihost=onwithout a hostid,versionon a feature-flag pool, acompatibilityfile that does not exist; - what it implies: enabling a feature is a one-way door that can make the pool
unreadable for older systems and boot loaders (keep a boot pool within
compatibility=grub2or the loader's list),failmode=panic/continue,cachefile=nonemeans no import at boot,autoreplaceneeds zfsd,delegation=offswitches everyzfs allowoff,autotrimload on cheap SSDs, abootfschange changes what boots; - on vdevs: what the kernel refuses (
bootsizeis read-only whatever vdevprops(7) says,pathonly on a leaf and only under/dev/,allocatingonly on a top-level vdev,sit_out/autositonly on raidz/draid, the root vdev needsfeature@vdev_zaps_v2) and what it implies (a threshold on a leaf is lost when the leaf is replaced — set it on the top-level vdev; zfsd must be running for the thresholds to matter;allocating=offdrains the vdev forzpool remove;failfast=offhides a dying plain disk from zfsd for longer).
zpool-set -list [-local] [-json] [-vdev VDEV…] [pool]
zpool-set -get PROP[,PROP…] [-json] [-vdev VDEV…] [pool]
zpool-set -set PROP=VALUE [-set PROP=VALUE…] [-vdev VDEV…] [-n|-y|-check] [pool]
zpool-set -reset PROP [-reset PROP…] [-vdev VDEV…] [-n|-y|-check] [pool]
zpool-set -enable FEATURE [-enable FEATURE…] [-n|-y|-check] [pool]
zpool-set -vdevs [-json] [pool]
zpool-set -where PROP [-json]
zpool-set -dump [pool] > F
zpool-set -restore F [-n|-y|-check]
zpool-set -catalogue [-json]
zpool-set -describe PROP [-json]
-set, -reset and -enable may be repeated; values are validated against
the catalogue before anything runs. -n prints the commands, -check exits 3
if anything would change (for configuration management), -y applies without
asking. The pool defaults to the one the current directory is on; a path on
a ZFS file system (., /usr/local/etc) stands for the pool holding it.
# zpool-set -set autoexpand=on -set failmode=continue -enable blake3 -n tank
zpool set autoexpand=on tank
zpool set failmode=continue tank
zpool set feature@blake3=enabled tank
note: failmode=continue: writes fail with EIO while the devices are gone; …
note: enabling blake3 is a one-way door: …
# zpool-set -dump tank > tank.json
# zpool-set -restore tank.json -check || zpool-set -restore tank.json -y
-vdev VDEV (repeatable; a name as zpool status prints it, root, a
leaf's path, or all) points -list, -get, -set and -reset at the
vdev's properties instead of the pool's; -vdevs prints the tree. The same
-set on several -vdevs applies to each — the fault thresholds are best
set on every top-level vdev, since a leaf's value does not survive its
replacement. -dump records the vdev properties too, and -restore puts
them back vdev by vdev. -describe knows both catalogues and prints both
entries for a name that exists on both sides (comment, ashift).
# zpool-set -vdevs tank
VDEV TYPE STATE SIZE ALLOC FREE FRAG R/W/C-ERR ASHIFT COMMENT
root-0 root ONLINE 21.8T 13.4T 8.42T 23% 0/0/0 0
mirror-0 mirror ONLINE 3.62T 2.90T 740G 31% 0/0/0 12
da0p3 disk ONLINE 3.64T - - - 0/0/0 12 /dev/da0p3 bay 1
…
# zpool-set -set io_n=10 -set io_t=60 -vdev mirror-0 -vdev raidz2-1 -n tank
zpool set io_n=10 tank mirror-0
zpool set io_n=10 tank raidz2-1
zpool set io_t=60 tank mirror-0
zpool set io_t=60 tank raidz2-1
# zpool-set -set 'comment=bay 4, WD-WCC4E9999999' -vdev /dev/da4 tank
- There is no
zpool inherit: a property goes back to its default by being set to it (zpool set failmode=wait), and a user property is removed with an empty value (zpool set module:name=). zpool-set does that for you. altrootandreadonlyonly exist atzpool create/zpool importtime.- A feature can only be enabled; once active (most become active on first
use) it cannot be disabled, and systems that lack it cannot import the pool
—
compatibilityis the guard rail, and it does not undo what is already enabled. ashiftonly seeds future vdev operations; existing vdevs keep theirs.- A pool
commentis at most 32 printable ASCII characters; a vdev comment is any text up to 8192 bytes. - Vdev properties have no reset either: a fault threshold goes back to
-(the daemon's own default: zfsd 50 errors in 60 s, zed 10 in 600 s) by being set to 2^64-1, which the kernel reads as "not set";pathhas no way back.bootsizeis read-only despite vdevprops(7) listing it as settable.sit_out,autositandraidz_expandingonly exist on raidz/draid vdevs, andzpool get … all-vdevsskips indirect (removed) vdevs.
~/.config/zpool-set/config ($XDG_CONFIG_HOME/zpool-set/config, or
ZPOOLSET_CONFIG) holds defaults for the interactive comforts, one
option = value per line, # comments:
mouse = on # -mouse by default (m still toggles it)
features = off # start with the features hidden (f shows them)
color = off # no colour (the same as NO_COLOR in the environment)
Command-line flags override the file; unknown keys and bad values are warned about, never fatal. Nothing that changes a pool can be set there.
go test ./...
The parsers are pinned by golden zpool get outputs (pool and all-vdevs)
taken on FreeBSD 15 / OpenZFS 2.4, the catalogues by the table zpool get
prints and by what the kernel reports on a vdev. Validation, plan building,
pre-flight, the vdev tree, the editor, the pickers, the mouse geometry and
the config file are pure and tested without a pool.
BSD 2-clause.


