Skip to content

Repository files navigation

zpool-set

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.

Install

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/.

Interactive

zpool-set [pool]

main screen

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

vdev tree

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.

property editor

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, a bootfs outside the pool or that does not exist, multihost=on without a hostid, version on a feature-flag pool, a compatibility file 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=grub2 or the loader's list), failmode=panic/continue, cachefile=none means no import at boot, autoreplace needs zfsd, delegation=off switches every zfs allow off, autotrim load on cheap SSDs, a bootfs change changes what boots;
  • on vdevs: what the kernel refuses (bootsize is read-only whatever vdevprops(7) says, path only on a leaf and only under /dev/, allocating only on a top-level vdev, sit_out/autosit only on raidz/draid, the root vdev needs feature@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=off drains the vdev for zpool remove; failfast=off hides a dying plain disk from zfsd for longer).

Scripting

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

Things it knows that the man page does not say loudly

  • 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.
  • altroot and readonly only exist at zpool create / zpool import time.
  • 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 — compatibility is the guard rail, and it does not undo what is already enabled.
  • ashift only seeds future vdev operations; existing vdevs keep theirs.
  • A pool comment is 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"; path has no way back. bootsize is read-only despite vdevprops(7) listing it as settable. sit_out, autosit and raidz_expanding only exist on raidz/draid vdevs, and zpool get … all-vdevs skips indirect (removed) vdevs.

Configuration

~/.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.

Tests

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.

License

BSD 2-clause.

About

Terminal UI and CLI for ZFS pool properties (zpool get / zpool set), for FreeBSD

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages