package module
v0.4.0 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Jan 22, 2022 License: BSD-3-Clause Imports: 13 Imported by: 5



go-libzfs currently implements basic manipulation of ZFS pools and data sets. Plan is to add more in further development, improve documentation with more examples, and add more tests. go-libzfs use libzfs C library and does not wrap OpenZFS CLI tools. Goal is to let easy using and manipulating OpenZFS form with in go, and tries to map libzfs C library in to go style package respecting golang common practice.


This golang package is only used and tested on Linux.

  • Version tagged as v0.1 is latest used and compatible with ZFS On Linux version 0.6.5.x
  • Version tagged as v0.2 is latest used and compatible with ZFS On Linux version 0.7.x


Main features

  • Creating, destroying, importing and exporting pools.
  • Reading and modifying pool properties.
  • Creating, destroying and renaming of filesystem datasets and volumes.
  • Creating, destroying and rollback of snapshots.
  • Cloning datasets and volumes.
  • Reading and modifying dataset and volume properties.
  • Send and receive snapshot streams


  • OpenZFS on Linux and libzfs with development headers installed.
  • Developed using go1.9


go get github.com/bicomsystems/go-libzfs


# On command line shell run
cd $GOPATH/src/github.com/bicomsystems/go-libzfs
go test

Usage example

// Create map to represent ZFS dataset properties. This is equivalent to
// list of properties you can get from ZFS CLI tool, and some more
// internally used by libzfs.
props := make(map[ZFSProp]Property)

// I choose to create (block) volume 1GiB in size. Size is just ZFS dataset
// property and this is done as map of strings. So, You have to either
// specify size as base 10 number in string, or use strconv package or
// similar to convert in to string (base 10) from numeric type.
strSize := "1073741824"

props[DatasetPropVolsize] = Property{Value: strSize}
// In addition I explicitly choose some more properties to be set.
props[DatasetPropVolblocksize] = Property{Value: "4096"}
props[DatasetPropReservation] = Property{Value: strSize}

// Lets create desired volume
d, err := DatasetCreate("TESTPOOL/VOLUME1", DatasetTypeVolume, props)
if err != nil {
// Dataset have to be closed for memory cleanup
defer d.Close()

println("Created zfs volume TESTPOOL/VOLUME1")

Special thanks to

  • Bicom Systems for supporting this little project and that way making it possible.
  • OpenZFS as the main ZFS software collective.



Package zfs implements basic manipulation of ZFS pools and data sets. Use libzfs C library instead CLI zfs tools, with goal to let using and manipulating OpenZFS form with in go project.

TODO: Adding to the pool. (Add the given vdevs to the pool) TODO: Scan for pools.




View Source
const (
	VDevTypeRoot      VDevType = "root"      // VDevTypeRoot root device in ZFS pool
	VDevTypeMirror             = "mirror"    // VDevTypeMirror mirror device in ZFS pool
	VDevTypeReplacing          = "replacing" // VDevTypeReplacing replacing
	VDevTypeRaidz              = "raidz"     // VDevTypeRaidz RAIDZ device
	VDevTypeDisk               = "disk"      // VDevTypeDisk device is disk
	VDevTypeFile               = "file"      // VDevTypeFile device is file
	VDevTypeMissing            = "missing"   // VDevTypeMissing missing device
	VDevTypeHole               = "hole"      // VDevTypeHole hole
	VDevTypeSpare              = "spare"     // VDevTypeSpare spare device
	VDevTypeLog                = "log"       // VDevTypeLog ZIL device
	VDevTypeL2cache            = "l2cache"   // VDevTypeL2cache cache device (disk)

Types of Virtual Devices

View Source
const (
	ESuccess              = 0               /* no error -- success */
	ENomem                = 2000 + iota - 1 /* out of memory */
	EBadprop                                /* invalid property value */
	EPropreadonly                           /* cannot set readonly property */
	EProptype                               /* property does not apply to dataset type */
	EPropnoninherit                         /* property is not inheritable */
	EPropspace                              /* bad quota or reservation */
	EBadtype                                /* dataset is not of appropriate type */
	EBusy                                   /* pool or dataset is busy */
	EExists                                 /* pool or dataset already exists */
	ENoent                                  /* no such pool or dataset */
	EBadstream                              /* bad backup stream */
	EDsreadonly                             /* dataset is readonly */
	EVoltoobig                              /* volume is too large for 32-bit system */
	EInvalidname                            /* invalid dataset name */
	EBadrestore                             /* unable to restore to destination */
	EBadbackup                              /* backup failed */
	EBadtarget                              /* bad attach/detach/replace target */
	ENodevice                               /* no such device in pool */
	EBaddev                                 /* invalid device to add */
	ENoreplicas                             /* no valid replicas */
	EResilvering                            /* currently resilvering */
	EBadversion                             /* unsupported version */
	EPoolunavail                            /* pool is currently unavailable */
	EDevoverflow                            /* too many devices in one vdev */
	EBadpath                                /* must be an absolute path */
	ECrosstarget                            /* rename or clone across pool or dataset */
	EZoned                                  /* used improperly in local zone */
	EMountfailed                            /* failed to mount dataset */
	EUmountfailed                           /* failed to unmount dataset */
	EUnsharenfsfailed                       /* unshare(1M) failed */
	ESharenfsfailed                         /* share(1M) failed */
	EPerm                                   /* permission denied */
	ENospc                                  /* out of space */
	EFault                                  /* bad address */
	EIo                                     /* I/O error */
	EIntr                                   /* signal received */
	EIsspare                                /* device is a hot spare */
	EInvalconfig                            /* invalid vdev configuration */
	ERecursive                              /* recursive dependency */
	ENohistory                              /* no history object */
	EPoolprops                              /* couldn't retrieve pool props */
	EPoolNotsup                             /* ops not supported for this type of pool */
	EPoolInvalarg                           /* invalid argument for this pool operation */
	ENametoolong                            /* dataset name is too long */
	EOpenfailed                             /* open of device failed */
	ENocap                                  /* couldn't get capacity */
	ELabelfailed                            /* write of label failed */
	EBadwho                                 /* invalid permission who */
	EBadperm                                /* invalid permission */
	EBadpermset                             /* invalid permission set name */
	ENodelegation                           /* delegated administration is disabled */
	EUnsharesmbfailed                       /* failed to unshare over smb */
	ESharesmbfailed                         /* failed to share over smb */
	EBadcache                               /* bad cache file */
	EIsl2CACHE                              /* device is for the level 2 ARC */
	EVdevnotsup                             /* unsupported vdev type */
	ENotsup                                 /* ops not supported on this dataset */
	EActiveSpare                            /* pool has active shared spare devices */
	EUnplayedLogs                           /* log device has unplayed logs */
	EReftagRele                             /* snapshot release: tag not found */
	EReftagHold                             /* snapshot hold: tag already exists */
	ETagtoolong                             /* snapshot hold/rele: tag too long */
	EPipefailed                             /* pipe create failed */
	EThreadcreatefailed                     /* thread create failed */
	EPostsplitOnline                        /* onlining a disk after splitting it */
	EScrubbing                              /* currently scrubbing */
	ENoScrub                                /* no active scrub */
	EDiff                                   /* general failure of zfs diff */
	EDiffdata                               /* bad zfs diff data */
	EPoolreadonly                           /* pool is in read-only mode */
	EScrubpaused                            /* scrub currently paused */
	EActivepool                             /* pool is imported on a different system */
	ECryptofailed                           /* failed to setup encryption */
	ENopending                              /* cannot cancel, no operation is pending */
	ECheckpointExists                       /* checkpoint exists */
	EDiscardingCheckpoint                   /* currently discarding a checkpoint */
	ENoCheckpoint                           /* pool has no checkpoint */
	EDevrmInProgress                        /* a device is currently being removed */
	EVdevTooBig                             /* a device is too big to be used */
	EIocNotsupported                        /* operation not supported by zfs module */
	EToomany                                /* argument list too long */
	EInitializing                           /* currently initializing */
	ENoInitialize                           /* no active initialize */
	EWrongParent                            /* invalid parent dataset (e.g ZVOL) */
	ETrimming                               /* currently trimming */
	ENoTrim                                 /* no active trim */
	ETrimNotsup                             /* device does not support trim */
	ENoResilverDefer                        /* pool doesn't support resilver_defer */
	EExportInProgress                       /* currently exporting the pool */
	ERebuilding                             /* resilvering (sequential reconstrution) */

ZFS errors

View Source
const (
	// DatasetTypeFilesystem - file system dataset
	DatasetTypeFilesystem DatasetType = (1 << 0)
	// DatasetTypeSnapshot - snapshot of dataset
	DatasetTypeSnapshot = (1 << 1)
	// DatasetTypeVolume - volume (virtual block device) dataset
	DatasetTypeVolume = (1 << 2)
	// DatasetTypePool - pool dataset
	DatasetTypePool = (1 << 3)
	// DatasetTypeBookmark - bookmark dataset
	DatasetTypeBookmark = (1 << 4)
View Source
const (
	FENABLED  = "enabled"
	FDISABLED = "disabled"

Enable or disable pool feature with this constants

View Source
const (
	ZIOTypeNull = iota

* ZIO types. Needed to interpret vdev statistics below.

View Source
const (
	DSSNone      = iota // No scan
	DSSScanning         // Scanning
	DSSFinished         // Scan finished
	DSSCanceled         // Scan canceled
	DSSNumStates        // Total number of scan states

Scan states

View Source
const (
	PoolScanNone     = iota // No scan function
	PoolScanScrub           // Pools is checked against errors
	PoolScanResilver        // Pool is resilvering
	PoolScanFuncs           // Number of scan functions

Scan functions


View Source
var Global struct {
	Mtx sync.Mutex

Global - global objects

View Source
var PoolStatusStrings = map[PoolStatus]string{
	PoolStatusCorruptCache:      "CORRUPT_CACHE",
	PoolStatusMissingDevR:       "MISSING_DEV_R",
	PoolStatusMissingDevNr:      "MISSING_DEV_NR",
	PoolStatusCorruptLabelR:     "CORRUPT_LABEL_R",
	PoolStatusCorruptLabelNr:    "CORRUPT_LABEL_NR",
	PoolStatusBadGUIDSum:        "BAD_GUID_SUM",
	PoolStatusCorruptPool:       "CORRUPT_POOL",
	PoolStatusCorruptData:       "CORRUPT_DATA",
	PoolStatusFailingDev:        "FAILLING_DEV",
	PoolStatusVersionNewer:      "VERSION_NEWER",
	PoolStatusHostidMismatch:    "HOSTID_MISMATCH",
	PoolStatusHosidActive:       "HOSTID_ACTIVE",
	PoolStatusHostidRequired:    "HOSTID_REQUIRED",
	PoolStatusIoFailureWait:     "FAILURE_WAIT",
	PoolStatusIoFailureContinue: "FAILURE_CONTINUE",
	PoolStatusIOFailureMMP:      "HOSTID_FAILURE_MMP",
	PoolStatusBadLog:            "BAD_LOG",
	PoolStatusErrata:            "ERRATA",

	PoolStatusUnsupFeatRead:  "UNSUP_FEAT_READ",
	PoolStatusUnsupFeatWrite: "UNSUP_FEAT_WRITE",

	PoolStatusFaultedDevR:  "FAULTED_DEV_R",
	PoolStatusFaultedDevNr: "FAULTED_DEV_NR",

	PoolStatusVersionOlder:     "VERSION_OLDER",
	PoolStatusFeatDisabled:     "FEAT_DISABLED",
	PoolStatusResilvering:      "RESILVERIN",
	PoolStatusOfflineDev:       "OFFLINE_DEV",
	PoolStatusRemovedDev:       "REMOVED_DEV",
	PoolStatusRebuilding:       "REBUILDING",
	PoolStatusRebuildScrub:     "REBUILD_SCRUB",
	PoolStatusNonNativeAshift:  "NON_NATIVE_ASHIFT",
	PoolStatusCompatibilityErr: "COMPATIBILITY_ERR",
	PoolStatusIncompatibleFeat: "INCOMPATIBLE_FEAT",

	PoolStatusOk: "OK",


func ClearLastError

func ClearLastError() (err error)

ClearLastError force clear of any last error set by undeliying libzfs

func DatasetCloseAll

func DatasetCloseAll(datasets []Dataset)

DatasetCloseAll close all datasets in slice and all of its recursive children datasets

func DatasetPropertyToName

func DatasetPropertyToName(p Prop) (name string)

DatasetPropertyToName convert property to name ( returns built in string representation of property name). This is optional, you can represent each property with string name of choice.

func LastError

func LastError() (err error)

LastError get last underlying libzfs error description if any

func PoolCloseAll

func PoolCloseAll(pools []Pool)

PoolCloseAll close all pools in given slice

func PoolPropertyToName

func PoolPropertyToName(p Prop) (name string)

PoolPropertyToName convert property to name ( returns built in string representation of property name). This is optional, you can represent each property with string name of choice.

func PoolStateToName

func PoolStateToName(state PoolState) (name string)

PoolStateToName maps POOL STATE to string.


type Dataset

type Dataset struct {
	Type       DatasetType
	Properties map[Prop]Property
	Children   []Dataset
	// contains filtered or unexported fields

Dataset - ZFS dataset object

func DatasetCreate

func DatasetCreate(path string, dtype DatasetType,
	props map[Prop]Property) (d Dataset, err error)

DatasetCreate create a new filesystem or volume on path representing pool/dataset or pool/parent/dataset


Example of creating ZFS volume

package main

import (
	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	// Create map to represent ZFS dataset properties. This is equivalent to
	// list of properties you can get from ZFS CLI tool, and some more
	// internally used by libzfs.
	props := make(map[zfs.Prop]zfs.Property)

	// I choose to create (block) volume 1GiB in size. Size is just ZFS dataset
	// property and this is done as map of strings. So, You have to either
	// specify size as base 10 number in string, or use strconv package or
	// similar to convert in to string (base 10) from numeric type.
	strSize := "1073741824"

	props[zfs.DatasetPropVolsize] = zfs.Property{Value: strSize}
	// In addition I explicitly choose some more properties to be set.
	props[zfs.DatasetPropVolblocksize] = zfs.Property{Value: "4096"}
	props[zfs.DatasetPropReservation] = zfs.Property{Value: strSize}

	// Lets create desired volume
	d, err := zfs.DatasetCreate("TESTPOOL/VOLUME1", zfs.DatasetTypeVolume, props)
	if err != nil {
	// Dataset have to be closed for memory cleanup
	defer d.Close()

	println("Created zfs volume TESTPOOL/VOLUME1")

func DatasetOpen

func DatasetOpen(path string) (d Dataset, err error)

DatasetOpen open dataset and all of its recursive children datasets

package main

import (
	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	// Open dataset and read its available space
	d, err := zfs.DatasetOpen("TESTPOOL/DATASET1")
	if err != nil {
	defer d.Close()
	var p zfs.Property
	if p, err = d.GetProperty(zfs.DatasetPropAvailable); err != nil {
	println(zfs.DatasetPropertyToName(zfs.DatasetPropAvailable), " = ",

func DatasetOpenAll

func DatasetOpenAll() (datasets []Dataset, err error)

DatasetOpenAll recursive get handles to all available datasets on system (file-systems, volumes or snapshots).

package main

import (

	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	datasets, err := zfs.DatasetOpenAll()
	if err != nil {
	defer zfs.DatasetCloseAll(datasets)

	// Print out path and type of root datasets
	for _, d := range datasets {
		path, err := d.Path()
		if err != nil {
		p, err := d.GetProperty(zfs.DatasetPropType)
		if err != nil {
		fmt.Printf("%30s | %10s\n", path, p.Value)


func DatasetOpenSingle

func DatasetOpenSingle(path string) (d Dataset, err error)

DatasetOpenSingle open dataset without opening all of its recursive children datasets

func DatasetSnapshot

func DatasetSnapshot(path string, recur bool, props map[Prop]Property) (rd Dataset, err error)

DatasetSnapshot create dataset snapshot. Set recur to true to snapshot child datasets.

func (*Dataset) Clone

func (d *Dataset) Clone(target string, props map[Prop]Property) (rd Dataset, err error)

Clone - clones the dataset. The target must be of the same type as the source.

func (*Dataset) Clones

func (d *Dataset) Clones() (clones []string, err error)

Clones - get list of all dataset paths cloned from this dataset or this snapshot List is sorted descedent by origin snapshot order

func (*Dataset) Close

func (d *Dataset) Close()

Close close dataset and all its recursive children datasets (close handle and cleanup dataset object/s from memory)

func (*Dataset) Destroy

func (d *Dataset) Destroy(Defer bool) (err error)

Destroy destroys the dataset. The caller must make sure that the filesystem isn't mounted, and that there are no active dependents. Set Defer argument to true to defer destruction for when dataset is not in use. Call Close() to cleanup memory.

func (*Dataset) DestroyPromote

func (d *Dataset) DestroyPromote() (err error)

DestroyPromote - Same as DestroyRecursive() except it will not destroy any dependent clones, but promote them first. This function will navigate any dependency chain of cloned datasets using breadth first search to promote according and let you remove dataset regardless of its cloned dependencies. Note: that this function wan't work when you want to destroy snapshot this way. However it will destroy all snaphsot of destroyed dataset without dependencies, otherwise snapshot will move to promoted clone

func (*Dataset) DestroyRecursive

func (d *Dataset) DestroyRecursive() (err error)

DestroyRecursive recursively destroy children of dataset and dataset.

func (*Dataset) FindSnapshot

func (d *Dataset) FindSnapshot(path string) (ok bool, snap Dataset)

FindSnapshot - returns true if given path is one of dataset snaphsots

func (*Dataset) FindSnapshotName

func (d *Dataset) FindSnapshotName(name string) (ok bool, snap Dataset)

FindSnapshotName - returns true and snapshot if given snapshot name eg. '@snap1' is one of dataset snaphsots

func (*Dataset) GetProperty

func (d *Dataset) GetProperty(p Prop) (prop Property, err error)

GetProperty reload and return single specified property. This also reloads requested property in Properties map.

func (*Dataset) GetUserProperty

func (d *Dataset) GetUserProperty(p string) (prop Property, err error)

GetUserProperty - lookup and return user propery

func (*Dataset) Hold

func (d *Dataset) Hold(flag string) (err error)

Hold - Adds a single reference, named with the tag argument, to the snapshot. Each snapshot has its own tag namespace, and tags must be unique within that space.

func (*Dataset) Holds

func (d *Dataset) Holds() (tags []HoldTag, err error)

Holds - Lists all existing user references for the given snapshot

func (*Dataset) IsMounted

func (d *Dataset) IsMounted() (mounted bool, where string)

IsMounted checks to see if the mount is active. If the filesystem is mounted, sets in 'where' argument the current mountpoint, and returns true. Otherwise, returns false.

func (*Dataset) IsSnapshot

func (d *Dataset) IsSnapshot() (ok bool)

IsSnapshot - retrun true if datset is snapshot

func (*Dataset) Mount

func (d *Dataset) Mount(options string, flags int) (err error)

Mount the given filesystem.

func (*Dataset) Path

func (d *Dataset) Path() (path string, err error)

Path return zfs dataset path/name

func (*Dataset) Pool

func (d *Dataset) Pool() (p Pool, err error)

Pool returns pool dataset belongs to

func (*Dataset) PoolName

func (d *Dataset) PoolName() string

PoolName - return name of the pool

func (*Dataset) Promote

func (d *Dataset) Promote() (err error)

Promote promotes dataset clone

func (*Dataset) Receive

func (d *Dataset) Receive(inf *os.File, flags RecvFlags) (err error)

Receive - receive snapshot stream

func (*Dataset) Release

func (d *Dataset) Release(flag string) (err error)

Release - Removes a single reference, named with the tag argument, from the specified snapshot. The tag must already exist for each snapshot. If a hold exists on a snapshot, attempts to destroy

that snapshot by using the zfs destroy command return EBUSY.

func (*Dataset) ReloadProperties

func (d *Dataset) ReloadProperties() (err error)

ReloadProperties re-read dataset's properties

func (*Dataset) Rename

func (d *Dataset) Rename(newName string, recur,
	forceUnmount bool) (err error)

Rename dataset

func (*Dataset) Rename2 added in v0.4.0

func (d *Dataset) Rename2(newName string, flags RenameFlags) (err error)

Rename2 dataset for ZFS 2.0.x with an option to rename a filesystem without needing to remount

func (*Dataset) Rollback

func (d *Dataset) Rollback(snap *Dataset, force bool) (err error)

Rollback rollabck's dataset snapshot

func (*Dataset) Send

func (d *Dataset) Send(outf *os.File, flags SendFlags) (err error)

func (*Dataset) SendFrom

func (d *Dataset) SendFrom(FromName string, outf *os.File, flags SendFlags) (err error)

func (*Dataset) SendResume added in v0.3.0

func (d *Dataset) SendResume(outf *os.File, flags *SendFlags, receiveResumeToken string) (err error)

func (*Dataset) SendSize

func (d *Dataset) SendSize(FromName string, flags SendFlags) (size int64, err error)

SendSize - estimate snapshot size to transfer

func (*Dataset) SetProperty

func (d *Dataset) SetProperty(p Prop, value string) (err error)

SetProperty set ZFS dataset property to value. Not all properties can be set, some can be set only at creation time and some are read only. Always check if returned error and its description.

func (*Dataset) SetUserProperty

func (d *Dataset) SetUserProperty(prop, value string) (err error)

SetUserProperty -

func (*Dataset) Snapshots

func (d *Dataset) Snapshots() (snaps []Dataset, err error)

Snapshots - filter and return all snapshots of dataset

func (*Dataset) Unmount

func (d *Dataset) Unmount(flags int) (err error)

Unmount the given filesystem.

func (*Dataset) UnmountAll

func (d *Dataset) UnmountAll(flags int) (err error)

UnmountAll unmount this filesystem and any children inheriting the mountpoint property.

type DatasetProperties

type DatasetProperties map[Prop]string

DatasetProperties type is map of dataset or volume properties prop -> value

type DatasetType

type DatasetType int32

DatasetType defines enum of dataset types

type ExportedPool

type ExportedPool struct {
	VDevs   VDevTree
	Name    string
	Comment string
	GUID    uint64
	State   PoolState
	Status  PoolStatus

ExportedPool is type representing ZFS pool available for import

func PoolImportSearch

func PoolImportSearch(searchpaths []string) (epools []ExportedPool, err error)

PoolImportSearch - Search pools available to import but not imported. Returns array of found pools.

type HoldTag

type HoldTag struct {
	Name      string
	Timestamp time.Time

HoldTag - user holds tags

type Pool

type Pool struct {
	Properties []Property
	Features   map[string]string
	// contains filtered or unexported fields

Pool object represents handler to single ZFS pool

Pool.Properties map[string]Property

Map of all ZFS pool properties, changing any of this will not affect ZFS pool, for that use SetProperty( name, value string) method of the pool object. This map is initial loaded when ever you open or create pool to give easy access to listing all available properties. It can be refreshed with up to date values with call to (*Pool) ReloadProperties

func PoolCreate

func PoolCreate(name string, vdev VDevTree, features map[string]string,
	props PoolProperties, fsprops DatasetProperties) (pool Pool, err error)

PoolCreate create ZFS pool per specs, features and properties of pool and root dataset

package main

import (
	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	disks := [2]string{"/dev/disk/by-id/ATA-123", "/dev/disk/by-id/ATA-456"}

	var vdev zfs.VDevTree
	var vdevs, mdevs, sdevs []zfs.VDevTree

	// build mirror devices specs
	for _, d := range disks {
		mdevs = append(mdevs,
			zfs.VDevTree{Type: zfs.VDevTypeDisk, Path: d})

	// spare device specs
	sdevs = []zfs.VDevTree{
		{Type: zfs.VDevTypeDisk, Path: "/dev/disk/by-id/ATA-789"}}

	// pool specs
	vdevs = []zfs.VDevTree{
		zfs.VDevTree{Type: zfs.VDevTypeMirror, Devices: mdevs},

	vdev.Devices = vdevs
	vdev.Spares = sdevs

	// pool properties
	props := make(map[zfs.Prop]string)
	props[zfs.PoolPropFailuremode] = "continue"
	// root dataset filesystem properties
	fsprops := make(map[zfs.Prop]string)
	// pool features
	features := make(map[string]string)

	// Turn off auto mounting by ZFS
	fsprops[zfs.DatasetPropMountpoint] = "none"

	// Enable some features
	features["async_destroy"] = "enabled"
	features["empty_bpobj"] = "enabled"
	features["lz4_compress"] = "enabled"

	// Based on specs formed above create test pool as 2 disk mirror and
	// one spare disk
	pool, err := zfs.PoolCreate("TESTPOOL", vdev, features, props, fsprops)
	if err != nil {
		println("Error: ", err.Error())
	defer pool.Close()

func PoolImport

func PoolImport(name string, searchpaths []string) (pool Pool, err error)

PoolImport given a list of directories to search, find and import pool with matching name stored on disk.

package main

import (
	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	p, err := zfs.PoolImport("TESTPOOL", []string{"/dev/disk/by-id"})
	if err != nil {

func PoolImportByGUID

func PoolImportByGUID(guid string, searchpaths []string) (pool Pool, err error)

PoolImportByGUID given a list of directories to search, find and import pool with matching GUID stored on disk.

func PoolOpen

func PoolOpen(name string) (pool Pool, err error)

PoolOpen open ZFS pool handler by name. Returns Pool object, requires Pool.Close() to be called explicitly for memory cleanup after object is not needed anymore.

func PoolOpenAll

func PoolOpenAll() (pools []Pool, err error)

PoolOpenAll open all active ZFS pools on current system. Returns array of Pool handlers, each have to be closed after not needed anymore. Call Pool.Close() method.


Open and list all pools on system with them properties

package main

import (

	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	// Lets open handles to all active pools on system
	pools, err := zfs.PoolOpenAll()
	if err != nil {

	// Print each pool name and properties
	for _, p := range pools {
		// Print fancy header
		fmt.Printf("\n -----------------------------------------------------------\n")
		fmt.Printf("   POOL: %49s   \n", p.Properties[zfs.PoolPropName].Value)
		fmt.Printf("|  PROPERTY      |  VALUE                |  SOURCE          |\n")

		// Iterate pool properties and print name, value and source
		for key, prop := range p.Properties {
			pkey := zfs.Prop(key)
			if pkey == zfs.PoolPropName {
				continue // Skip name its already printed above
			fmt.Printf("|%14s  | %20s  | %15s  |\n",
				prop.Value, prop.Source)

		// Close pool handle and free memory, since it will not be used anymore

func (*Pool) CancelInitialization added in v0.3.4

func (pool *Pool) CancelInitialization() (err error)

CancelInitialization - cancels ongoing initialization

func (*Pool) Clear

func (pool *Pool) Clear(device string) (err error)

Clear - Clear all errors associated with a pool or a particular device.

func (*Pool) Close

func (pool *Pool) Close()

Close ZFS pool handler and release associated memory. Do not use Pool object after this.

func (*Pool) Destroy

func (pool *Pool) Destroy(logStr string) (err error)

Destroy the pool. It is up to the caller to ensure that there are no datasets left in the pool. logStr is optional if specified it is appended to ZFS history

package main

import (
	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	pname := "TESTPOOL"

	// Need handle to pool at first place
	p, err := zfs.PoolOpen(pname)
	if err != nil {
		println("Error: ", err.Error())

	// Make sure pool handle is free after we are done here
	defer p.Close()

	if err = p.Destroy("Example of pool destroy (TESTPOOL)"); err != nil {
		println("Error: ", err.Error())

func (*Pool) Export

func (pool *Pool) Export(force bool, log string) (err error)

Export exports the pool from the system. Before exporting the pool, all datasets within the pool are unmounted. A pool can not be exported if it has a shared spare that is currently being used.

package main

import (
	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	p, err := zfs.PoolOpen("TESTPOOL")
	if err != nil {
	defer p.Close()
	if err = p.Export(false, "Example exporting pool"); err != nil {

func (*Pool) ExportForce

func (pool *Pool) ExportForce(log string) (err error)

ExportForce hard force export of the pool from the system.

package main

import (
	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	p, err := zfs.PoolOpen("TESTPOOL")
	if err != nil {
	defer p.Close()
	if err = p.ExportForce("Example exporting pool"); err != nil {

func (*Pool) GetFeature

func (pool *Pool) GetFeature(name string) (value string, err error)

GetFeature reload and return single specified feature. This also reloads requested feature in Features map.

func (*Pool) GetProperty

func (pool *Pool) GetProperty(p Prop) (prop Property, err error)

GetProperty reload and return single specified property. This also reloads requested property in Properties map.

func (*Pool) Initialize added in v0.3.4

func (pool *Pool) Initialize() (err error)

Initialize - initializes pool

func (*Pool) Name

func (pool *Pool) Name() (name string, err error)

Name get (re-read) ZFS pool name property

func (*Pool) Offline

func (pool *Pool) Offline(force bool, devs ...string) (err error)

Offline Take the device/s in offline state

func (*Pool) OfflineTemp

func (pool *Pool) OfflineTemp(force bool, devs ...string) (err error)

OfflineTemp Take the device/s in offline state temporary, upon reboot, the specified physical device reverts to its previous state. force - Force the device into a faulted state.

func (*Pool) Online

func (pool *Pool) Online(expand bool, devs ...string) (err error)

Online try to set dev online expand - expand storage

func (*Pool) RefreshStats

func (pool *Pool) RefreshStats() (err error)

RefreshStats the pool's vdev statistics, e.g. bytes read/written.

func (*Pool) ReloadProperties

func (pool *Pool) ReloadProperties() (err error)

ReloadProperties re-read ZFS pool properties and features, refresh Pool.Properties and Pool.Features map

func (*Pool) SetProperty

func (pool *Pool) SetProperty(p Prop, value string) (err error)

SetProperty set ZFS pool property to value. Not all properties can be set, some can be set only at creation time and some are read only. Always check if returned error and its description.

func (*Pool) State

func (pool *Pool) State() (state PoolState, err error)

State get ZFS pool state Return the state of the pool (ACTIVE or UNAVAILABLE)

package main

import (
	zfs "github.com/bicomsystems/go-libzfs"

func main() {
	p, err := zfs.PoolOpen("TESTPOOL")
	if err != nil {
	defer p.Close()
	pstate, err := p.State()
	if err != nil {
	println("POOL TESTPOOL state:", zfs.PoolStateToName(pstate))

func (*Pool) Status

func (pool *Pool) Status() (status PoolStatus, err error)

Status get pool status. Let you check if pool healthy.

func (*Pool) SuspendInitialization added in v0.3.4

func (pool *Pool) SuspendInitialization() (err error)

SuspendInitialization - suspends ongoing initialization

func (*Pool) VDevTree

func (pool *Pool) VDevTree() (vdevs VDevTree, err error)

VDevTree - Fetch pool's current vdev tree configuration, state and stats

type PoolInitializeAction added in v0.3.4

type PoolInitializeAction int

PoolInitializeAction type representing pool initialize action

const (
	PoolInitializeStart   PoolInitializeAction = iota // start initialization
	PoolInitializeCancel                              // cancel initialization
	PoolInitializeSuspend                             // suspend initialization

Initialize actions

func (PoolInitializeAction) String added in v0.3.4

func (s PoolInitializeAction) String() string

type PoolProperties

type PoolProperties map[Prop]string

PoolProperties type is map of pool properties name -> value

type PoolScanStat

type PoolScanStat struct {
	// Values stored on disk
	Func      uint64 // Current scan function e.g. none, scrub ...
	State     uint64 // Current scan state e.g. scanning, finished ...
	StartTime uint64 // Scan start time
	EndTime   uint64 // Scan end time
	ToExamine uint64 // Total bytes to scan
	Examined  uint64 // Total bytes scaned
	ToProcess uint64 // Total bytes to processed
	Processed uint64 // Total bytes processed
	Errors    uint64 // Scan errors
	// Values not stored on disk
	PassExam  uint64 // Examined bytes per scan pass
	PassStart uint64 // Start time of scan pass

PoolScanStat - Pool scan statistics

type PoolState

type PoolState uint64

PoolState type representing pool state

const (
	PoolStateActive            PoolState = iota /* In active use		*/
	PoolStateExported                           /* Explicitly exported		*/
	PoolStateDestroyed                          /* Explicitly destroyed		*/
	PoolStateSpare                              /* Reserved for hot spare use	*/
	PoolStateL2cache                            /* Level 2 ARC device		*/
	PoolStateUninitialized                      /* Internal spa_t state		*/
	PoolStateUnavail                            /* Internal libzfs state	*/
	PoolStatePotentiallyActive                  /* Internal libzfs state	*/

Possible ZFS pool states

func (PoolState) String

func (s PoolState) String() string

type PoolStatus

type PoolStatus int

PoolStatus type representing status of the pool

const (
	 * The following correspond to faults as defined in the (fault.fs.zfs.*)
	 * event namespace.  Each is associated with a corresponding message ID.
	PoolStatusCorruptCache      PoolStatus = iota /* corrupt /kernel/drv/zpool.cache */
	PoolStatusMissingDevR                         /* missing device with replicas */
	PoolStatusMissingDevNr                        /* missing device with no replicas */
	PoolStatusCorruptLabelR                       /* bad device label with replicas */
	PoolStatusCorruptLabelNr                      /* bad device label with no replicas */
	PoolStatusBadGUIDSum                          /* sum of device guids didn't match */
	PoolStatusCorruptPool                         /* pool metadata is corrupted */
	PoolStatusCorruptData                         /* data errors in user (meta)data */
	PoolStatusFailingDev                          /* device experiencing errors */
	PoolStatusVersionNewer                        /* newer on-disk version */
	PoolStatusHostidMismatch                      /* last accessed by another system */
	PoolStatusHosidActive                         /* currently active on another system */
	PoolStatusHostidRequired                      /* multihost=on and hostid=0 */
	PoolStatusIoFailureWait                       /* failed I/O, failmode 'wait' */
	PoolStatusIoFailureContinue                   /* failed I/O, failmode 'continue' */
	PoolStatusIOFailureMMP                        /* ailed MMP, failmode not 'panic' */
	PoolStatusBadLog                              /* cannot read log chain(s) */
	PoolStatusErrata                              /* informational errata available */

	 * If the pool has unsupported features but can still be opened in
	 * read-only mode, its status is ZPOOL_STATUS_UNSUP_FEAT_WRITE. If the
	 * pool has unsupported features but cannot be opened at all, its
	PoolStatusUnsupFeatRead  /* unsupported features for read */
	PoolStatusUnsupFeatWrite /* unsupported features for write */

	 * These faults have no corresponding message ID.  At the time we are
	 * checking the status, the original reason for the FMA fault (I/O or
	 * checksum errors) has been lost.
	PoolStatusFaultedDevR  /* faulted device with replicas */
	PoolStatusFaultedDevNr /* faulted device with no replicas */

	 * The following are not faults per se, but still an error possibly
	 * requiring administrative attention.  There is no corresponding
	 * message ID.
	PoolStatusVersionOlder     /* older legacy on-disk version */
	PoolStatusFeatDisabled     /* supported features are disabled */
	PoolStatusResilvering      /* device being resilvered */
	PoolStatusOfflineDev       /* device offline */
	PoolStatusRemovedDev       /* removed device */
	PoolStatusRebuilding       /* device being rebuilt */
	PoolStatusRebuildScrub     /* recommend scrubbing the pool */
	PoolStatusNonNativeAshift  /* (e.g. 512e dev with ashift of 9) */
	PoolStatusCompatibilityErr /* bad 'compatibility' property */
	PoolStatusIncompatibleFeat /* feature set outside compatibility */

	 * Finally, the following indicates a healthy pool.

Pool status

func (PoolStatus) String

func (s PoolStatus) String() string

type Prop

type Prop int

Prop type to enumerate all different properties suppoerted by ZFS

const (
	PoolPropCont Prop = iota - 2

Pool properties. Enumerates available ZFS pool properties. Use it to access pool properties either to read or set soecific property.

const (
	DatasetPropCont Prop = iota - 2
	DatasetPropPrivate /* not exposed to user, temporary */
	DatasetPropCreateTXG /* not exposed to the user */
	DatasetPropName      /* not exposed to the user */
	DatasetPropIscsioptions /* not exposed to the user */
	DatasetPropNumclones /* not exposed to the user */
	DatasetPropUseraccounting /* not exposed to the user */
	DatasetPropStmfShareinfo  /* not exposed to the user */
	DatasetPropUnique   /* not exposed to the user */
	DatasetPropObjsetid /* not exposed to the user */
	DatasetPropInconsistent /* not exposed to the user */
	DatasetPropRemapTXG /* not exposed to the user */
	DatasetPropIVSetGuid /* not exposed to the user */

* Dataset properties are identified by these constants and must be added to * the end of this list to ensure that external consumers are not affected * by the change. If you make any changes to this list, be sure to update * the property table in module/zcommon/zfs_prop.c.

type Property

type Property struct {
	Value  string
	Source string

Property ZFS pool or dataset property value

type RecvFlags

type RecvFlags struct {
	Verbose     bool // -v
	IsPrefix    bool // -d
	IsTail      bool // -e
	DryRun      bool // -n
	Force       bool // -r
	Resumable   bool // -s
	NoMount     bool // -u
	CanmountOff bool
	ByteSwap    bool

RecvFlags receive flags

type RenameFlags added in v0.4.0

type RenameFlags struct {
	// Recursive rename
	Recursive bool
	// Do not unmount file systems
	Nounmount bool
	// Force unmount file systems
	Forceunmount bool

RenameFlags structure contains information for ZFS 2.0.x Rename Dataset feature

type ResumeToken added in v0.3.4

type ResumeToken struct {
	ToName     string
	FromName   string
	Object     uint64
	Offset     uint64
	ToGUID     uint64
	FromGUID   uint64
	Bytes      uint64
	LargeBlock bool
	EmbedOk    bool
	CompressOk bool
	RawOk      bool

ResumeToken - informations extracted from resume token

func (*ResumeToken) Unpack added in v0.3.4

func (rt *ResumeToken) Unpack(token string) (err error)

Unpack unpack resume token

type SendFlags

type SendFlags struct {
	Verbosity  int  // -v
	Replicate  bool // -R
	DoAll      bool // -I
	FromOrigin bool // -o
	Props      bool // -p
	DryRun     bool // -n
	Parsable   bool // -P
	Progress   bool // show progress (ie. -v)
	LargeBlock bool // -L
	EmbedData  bool // -e
	Compress   bool // -c
	Raw        bool // raw encrypted records are permitted
	Backup     bool // only send received properties (ie. -b)
	Holds      bool // include snapshot holds in send stream

SendFlags send flags

type VDevAux

type VDevAux uint64

VDevAux - vdev aux states

const (
	VDevAuxNone            VDevAux = iota // no error
	VDevAuxOpenFailed                     // ldi_open_*() or vn_open() failed
	VDevAuxCorruptData                    // bad label or disk contents
	VDevAuxNoReplicas                     // insufficient number of replicas
	VDevAuxBadGUIDSum                     // vdev guid sum doesn't match
	VDevAuxTooSmall                       // vdev size is too small
	VDevAuxBadLabel                       // the label is OK but invalid
	VDevAuxVersionNewer                   // on-disk version is too new
	VDevAuxVersionOlder                   // on-disk version is too old
	VDevAuxUnsupFeat                      // unsupported features
	VDevAuxSpared                         // hot spare used in another pool
	VDevAuxErrExceeded                    // too many errors
	VDevAuxIOFailure                      // experienced I/O failure
	VDevAuxBadLog                         // cannot read log chain(s)
	VDevAuxExternal                       // external diagnosis
	VDevAuxSplitPool                      // vdev was split off into another pool
	VdevAuxBadAshift                      // vdev ashift is invalid
	VdevAuxExternalPersist                // persistent forced fault
	VdevAuxActive                         // vdev active on a different host
	VdevAuxChildrenOffline                // all children are offline
	VdevAuxAshiftTooBig                   // vdev's min block size is too large

vdev aux states. When a vdev is in the VDevStateCantOpen state, the aux field of the vdev stats structure uses these constants to distinguish why.

type VDevStat

type VDevStat struct {
	Timestamp      time.Duration    /* time since vdev load	(nanoseconds)*/
	State          VDevState        /* vdev state		*/
	Aux            VDevAux          /* see vdev_aux_t	*/
	Alloc          uint64           /* space allocated	*/
	Space          uint64           /* total capacity	*/
	DSpace         uint64           /* deflated capacity	*/
	RSize          uint64           /* replaceable dev size */
	ESize          uint64           /* expandable dev size */
	Ops            [ZIOTypes]uint64 /* operation count	*/
	Bytes          [ZIOTypes]uint64 /* bytes read/written	*/
	ReadErrors     uint64           /* read errors		*/
	WriteErrors    uint64           /* write errors		*/
	ChecksumErrors uint64           /* checksum errors	*/
	SelfHealed     uint64           /* self-healed bytes	*/
	ScanRemoving   uint64           /* removing?	*/
	ScanProcessed  uint64           /* scan processed bytes	*/
	Fragmentation  uint64           /* device fragmentation */

VDevStat - Vdev statistics. Note: all fields should be 64-bit because this is passed between kernel and userland as an nvlist uint64 array.

type VDevState

type VDevState uint64

VDevState - vdev states tye

const (
	VDevStateUnknown  VDevState = iota // Uninitialized vdev
	VDevStateClosed                    // Not currently open
	VDevStateOffline                   // Not allowed to open
	VDevStateRemoved                   // Explicitly removed from system
	VDevStateCantOpen                  // Tried to open, but failed
	VDevStateFaulted                   // External request to fault device
	VDevStateDegraded                  // Replicated vdev with unhealthy kids
	VDevStateHealthy                   // Presumed good

vdev states are ordered from least to most healthy. A vdev that's VDevStateCantOpen or below is considered unusable.

func (VDevState) String

func (s VDevState) String() string

type VDevTree

type VDevTree struct {
	Type     VDevType
	Devices  []VDevTree // groups other devices (e.g. mirror)
	Spares   []VDevTree
	L2Cache  []VDevTree
	Logs     *VDevTree
	GUID     uint64
	Parity   uint
	Path     string
	Name     string
	Stat     VDevStat
	ScanStat PoolScanStat

VDevTree ZFS virtual device tree

type VDevType

type VDevType string

VDevType type of device in the pool

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL