diff options
Diffstat (limited to 'sys/contrib/openzfs/man/man8/zfs-program.8')
-rw-r--r-- | sys/contrib/openzfs/man/man8/zfs-program.8 | 673 |
1 files changed, 673 insertions, 0 deletions
diff --git a/sys/contrib/openzfs/man/man8/zfs-program.8 b/sys/contrib/openzfs/man/man8/zfs-program.8 new file mode 100644 index 000000000000..d87042c4c0c7 --- /dev/null +++ b/sys/contrib/openzfs/man/man8/zfs-program.8 @@ -0,0 +1,673 @@ +.\" SPDX-License-Identifier: CDDL-1.0 +.\" +.\" This file and its contents are supplied under the terms of the +.\" Common Development and Distribution License ("CDDL"), version 1.0. +.\" You may only use this file in accordance with the terms of version +.\" 1.0 of the CDDL. +.\" +.\" A full copy of the text of the CDDL should have accompanied this +.\" source. A copy of the CDDL is also available via the Internet at +.\" http://www.illumos.org/license/CDDL. +.\" +.\" Copyright (c) 2016, 2019 by Delphix. All Rights Reserved. +.\" Copyright (c) 2019, 2020 by Christian Schwarz. All Rights Reserved. +.\" Copyright 2020 Joyent, Inc. +.\" Copyright (c) 2025, Rob Norris <robn@despairlabs.com> +.\" +.Dd June 5, 2025 +.Dt ZFS-PROGRAM 8 +.Os +. +.Sh NAME +.Nm zfs-program +.Nd execute ZFS channel programs +.Sh SYNOPSIS +.Nm zfs +.Cm program +.Op Fl jn +.Op Fl t Ar instruction-limit +.Op Fl m Ar memory-limit +.Ar pool +.Ar script +.Op Ar script arguments +. +.Sh DESCRIPTION +The ZFS channel program interface allows ZFS administrative operations to be +run programmatically as a Lua script. +The entire script is executed atomically, with no other administrative +operations taking effect concurrently. +A library of ZFS calls is made available to channel program scripts. +Channel programs may only be run with root privileges. +.Pp +A modified version of the Lua 5.2 interpreter is used to run channel program +scripts. +The Lua 5.2 manual can be found at +.Lk http://www.lua.org/manual/5.2/ +.Pp +The channel program given by +.Ar script +will be run on +.Ar pool , +and any attempts to access or modify other pools will cause an error. +. +.Sh OPTIONS +.Bl -tag -width "-t" +.It Fl j , -json +Display channel program output in JSON format. +When this flag is specified and standard output is empty - +channel program encountered an error. +The details of such an error will be printed to standard error in plain text. +.It Fl n +Executes a read-only channel program, which runs faster. +The program cannot change on-disk state by calling functions from the +zfs.sync submodule. +The program can be used to gather information such as properties and +determining if changes would succeed (zfs.check.*). +Without this flag, all pending changes must be synced to disk before a +channel program can complete. +.It Fl t Ar instruction-limit +Limit the number of Lua instructions to execute. +If a channel program executes more than the specified number of instructions, +it will be stopped and an error will be returned. +The default limit is 10 million instructions, and it can be set to a maximum of +100 million instructions. +.It Fl m Ar memory-limit +Memory limit, in bytes. +If a channel program attempts to allocate more memory than the given limit, it +will be stopped and an error returned. +The default memory limit is 10 MiB, and can be set to a maximum of 100 MiB. +.El +.Pp +All remaining argument strings will be passed directly to the Lua script as +described in the +.Sx LUA INTERFACE +section below. +. +.Sh LUA INTERFACE +A channel program can be invoked either from the command line, or via a library +call to +.Fn lzc_channel_program . +. +.Ss Arguments +Arguments passed to the channel program are converted to a Lua table. +If invoked from the command line, extra arguments to the Lua script will be +accessible as an array stored in the argument table with the key 'argv': +.Bd -literal -compact -offset indent +args = ... +argv = args["argv"] +-- argv == {1="arg1", 2="arg2", ...} +.Ed +.Pp +If invoked from the libzfs interface, an arbitrary argument list can be +passed to the channel program, which is accessible via the same +.Qq Li ... +syntax in Lua: +.Bd -literal -compact -offset indent +args = ... +-- args == {"foo"="bar", "baz"={...}, ...} +.Ed +.Pp +Note that because Lua arrays are 1-indexed, arrays passed to Lua from the +libzfs interface will have their indices incremented by 1. +That is, the element +in +.Va arr[0] +in a C array passed to a channel program will be stored in +.Va arr[1] +when accessed from Lua. +. +.Ss Return Values +Lua return statements take the form: +.Dl return ret0, ret1, ret2, ... +.Pp +Return statements returning multiple values are permitted internally in a +channel program script, but attempting to return more than one value from the +top level of the channel program is not permitted and will throw an error. +However, tables containing multiple values can still be returned. +If invoked from the command line, a return statement: +.Bd -literal -compact -offset indent +a = {foo="bar", baz=2} +return a +.Ed +.Pp +Will be output formatted as: +.Bd -literal -compact -offset indent +Channel program fully executed with return value: + return: + baz: 2 + foo: 'bar' +.Ed +. +.Ss Fatal Errors +If the channel program encounters a fatal error while running, a non-zero exit +status will be returned. +If more information about the error is available, a singleton list will be +returned detailing the error: +.Dl error: \&"error string, including Lua stack trace" +.Pp +If a fatal error is returned, the channel program may have not executed at all, +may have partially executed, or may have fully executed but failed to pass a +return value back to userland. +.Pp +If the channel program exhausts an instruction or memory limit, a fatal error +will be generated and the program will be stopped, leaving the program partially +executed. +No attempt is made to reverse or undo any operations already performed. +Note that because both the instruction count and amount of memory used by a +channel program are deterministic when run against the same inputs and +filesystem state, as long as a channel program has run successfully once, you +can guarantee that it will finish successfully against a similar size system. +.Pp +If a channel program attempts to return too large a value, the program will +fully execute but exit with a nonzero status code and no return value. +.Pp +.Em Note : +ZFS API functions do not generate Fatal Errors when correctly invoked, they +return an error code and the channel program continues executing. +See the +.Sx ZFS API +section below for function-specific details on error return codes. +. +.Ss Lua to C Value Conversion +When invoking a channel program via the libzfs interface, it is necessary to +translate arguments and return values from Lua values to their C equivalents, +and vice-versa. +.Pp +There is a correspondence between nvlist values in C and Lua tables. +A Lua table which is returned from the channel program will be recursively +converted to an nvlist, with table values converted to their natural +equivalents: +.TS +cw3 l c l . + string -> string + number -> int64 + boolean -> boolean_value + nil -> boolean (no value) + table -> nvlist +.TE +.Pp +Likewise, table keys are replaced by string equivalents as follows: +.TS +cw3 l c l . + string -> no change + number -> signed decimal string ("%lld") + boolean -> "true" | "false" +.TE +.Pp +Any collision of table key strings (for example, the string "true" and a +true boolean value) will cause a fatal error. +.Pp +Lua numbers are represented internally as signed 64-bit integers. +. +.Sh LUA STANDARD LIBRARY +The following Lua built-in base library functions are available: +.TS +cw3 l l l l . + assert rawlen collectgarbage rawget + error rawset getmetatable select + ipairs setmetatable next tonumber + pairs tostring rawequal type +.TE +.Pp +All functions in the +.Em coroutine , +.Em string , +and +.Em table +built-in submodules are also available. +A complete list and documentation of these modules is available in the Lua +manual. +.Pp +The following functions base library functions have been disabled and are +not available for use in channel programs: +.TS +cw3 l l l l l l . + dofile loadfile load pcall print xpcall +.TE +. +.Sh ZFS API +. +.Ss Function Arguments +Each API function takes a fixed set of required positional arguments and +optional keyword arguments. +For example, the destroy function takes a single positional string argument +(the name of the dataset to destroy) and an optional "defer" keyword boolean +argument. +When using parentheses to specify the arguments to a Lua function, only +positional arguments can be used: +.Dl Sy zfs.sync.destroy Ns Pq \&"rpool@snap" +.Pp +To use keyword arguments, functions must be called with a single argument that +is a Lua table containing entries mapping integers to positional arguments and +strings to keyword arguments: +.Dl Sy zfs.sync.destroy Ns Pq {1="rpool@snap", defer=true} +.Pp +The Lua language allows curly braces to be used in place of parenthesis as +syntactic sugar for this calling convention: +.Dl Sy zfs.sync.snapshot Ns {"rpool@snap", defer=true} +. +.Ss Function Return Values +If an API function succeeds, it returns 0. +If it fails, it returns an error code and the channel program continues +executing. +API functions do not generate Fatal Errors except in the case of an +unrecoverable internal file system error. +.Pp +In addition to returning an error code, some functions also return extra +details describing what caused the error. +This extra description is given as a second return value, and will always be a +Lua table, or Nil if no error details were returned. +Different keys will exist in the error details table depending on the function +and error case. +Any such function may be called expecting a single return value: +.Dl errno = Sy zfs.sync.promote Ns Pq dataset +.Pp +Or, the error details can be retrieved: +.Bd -literal -compact -offset indent +.No errno, details = Sy zfs.sync.promote Ns Pq dataset +if (errno == EEXIST) then + assert(details ~= Nil) + list_of_conflicting_snapshots = details +end +.Ed +.Pp +The following global aliases for API function error return codes are defined +for use in channel programs: +.TS +cw3 l l l l l l l . + EPERM ECHILD ENODEV ENOSPC ENOENT EAGAIN ENOTDIR + ESPIPE ESRCH ENOMEM EISDIR EROFS EINTR EACCES + EINVAL EMLINK EIO EFAULT ENFILE EPIPE ENXIO + ENOTBLK EMFILE EDOM E2BIG EBUSY ENOTTY ERANGE + ENOEXEC EEXIST ETXTBSY EDQUOT EBADF EXDEV EFBIG +.TE +. +.Ss API Functions +For detailed descriptions of the exact behavior of any ZFS administrative +operations, see the main +.Xr zfs 8 +manual page. +.Bl -tag -width "xx" +.It Fn zfs.debug msg +Record a debug message in the zfs_dbgmsg log. +A log of these messages can be printed via mdb's "::zfs_dbgmsg" command, or +can be monitored live by running +.Dl dtrace -n 'zfs-dbgmsg{trace(stringof(arg0))}' +.Pp +.Bl -tag -compact -width "property (string)" +.It Ar msg Pq string +Debug message to be printed. +.El +.It Fn zfs.exists dataset +Returns true if the given dataset exists, or false if it doesn't. +A fatal error will be thrown if the dataset is not in the target pool. +That is, in a channel program running on rpool, +.Sy zfs.exists Ns Pq \&"rpool/nonexistent_fs" +returns false, but +.Sy zfs.exists Ns Pq \&"somepool/fs_that_may_exist" +will error. +.Pp +.Bl -tag -compact -width "property (string)" +.It Ar dataset Pq string +Dataset to check for existence. +Must be in the target pool. +.El +.It Fn zfs.get_prop dataset property +Returns two values. +First, a string, number or table containing the property value for the given +dataset. +Second, a string containing the source of the property (i.e. the name of the +dataset in which it was set or nil if it is readonly). +Throws a Lua error if the dataset is invalid or the property doesn't exist. +Note that Lua only supports int64 number types whereas ZFS number properties +are uint64. +This means very large values (like GUIDs) may wrap around and appear negative. +.Pp +.Bl -tag -compact -width "property (string)" +.It Ar dataset Pq string +Filesystem or snapshot path to retrieve properties from. +.It Ar property Pq string +Name of property to retrieve. +All filesystem, snapshot and volume properties are supported except for +.Sy mounted +and +.Sy iscsioptions . +Also supports the +.Sy written@ Ns Ar snap +and +.Sy written# Ns Ar bookmark +properties and the +.Ao Sy user Ns | Ns Sy group Ac Ns Ao Sy quota Ns | Ns Sy used Ac Ns Sy @ Ns Ar id +properties, though the id must be in numeric form. +.El +.El +.Bl -tag -width "xx" +.It Sy zfs.sync submodule +The sync submodule contains functions that modify the on-disk state. +They are executed in "syncing context". +.Pp +The available sync submodule functions are as follows: +.Bl -tag -width "xx" +.It Fn zfs.sync.clone snapshot newdataset +Create a new filesystem from a snapshot. +Returns 0 if the filesystem was successfully created, +and a nonzero error code otherwise. +.Pp +Note: Due to general limitations in channel programs, a filesystem created +this way will not be mounted, regardless of the value of the +.Sy mountpoint +and +.Sy canmount +properties. +This limitation may be removed in the future, +so it is recommended that you set +.Sy mountpoint Ns = Ns Sy none +or +.Sy canmount Ns = Ns Sy off +or +.Sy noauto +to avoid surprises. +.Pp +.Bl -tag -compact -width "newbookmark (string)" +.It Ar snapshot Pq string +Name of the source snapshot to clone. +.It Ar newdataset Pq string +Name of the target dataset to create. +.El +.It Sy zfs.sync.destroy Ns Pq Ar dataset , Op Ar defer Ns = Ns Sy true Ns | Ns Sy false +Destroy the given dataset. +Returns 0 on successful destroy, or a nonzero error code if the dataset could +not be destroyed (for example, if the dataset has any active children or +clones). +.Pp +.Bl -tag -compact -width "newbookmark (string)" +.It Ar dataset Pq string +Filesystem or snapshot to be destroyed. +.It Op Ar defer Pq boolean +Valid only for destroying snapshots. +If set to true, and the snapshot has holds or clones, allows the snapshot to be +marked for deferred deletion rather than failing. +.El +.It Fn zfs.sync.inherit dataset property +Clears the specified property in the given dataset, causing it to be inherited +from an ancestor, or restored to the default if no ancestor property is set. +The +.Nm zfs Cm inherit Fl S +option has not been implemented. +Returns 0 on success, or a nonzero error code if the property could not be +cleared. +.Pp +.Bl -tag -compact -width "newbookmark (string)" +.It Ar dataset Pq string +Filesystem or snapshot containing the property to clear. +.It Ar property Pq string +The property to clear. +Allowed properties are the same as those for the +.Nm zfs Cm inherit +command. +.El +.It Fn zfs.sync.promote dataset +Promote the given clone to a filesystem. +Returns 0 on successful promotion, or a nonzero error code otherwise. +If EEXIST is returned, the second return value will be an array of the clone's +snapshots whose names collide with snapshots of the parent filesystem. +.Pp +.Bl -tag -compact -width "newbookmark (string)" +.It Ar dataset Pq string +Clone to be promoted. +.El +.It Fn zfs.sync.rollback filesystem +Rollback to the previous snapshot for a dataset. +Returns 0 on successful rollback, or a nonzero error code otherwise. +Rollbacks can be performed on filesystems or zvols, but not on snapshots +or mounted datasets. +EBUSY is returned in the case where the filesystem is mounted. +.Pp +.Bl -tag -compact -width "newbookmark (string)" +.It Ar filesystem Pq string +Filesystem to rollback. +.El +.It Fn zfs.sync.set_prop dataset property value +Sets the given property on a dataset. +Currently only user properties are supported. +Returns 0 if the property was set, or a nonzero error code otherwise. +.Pp +.Bl -tag -compact -width "newbookmark (string)" +.It Ar dataset Pq string +The dataset where the property will be set. +.It Ar property Pq string +The property to set. +.It Ar value Pq string +The value of the property to be set. +.El +.It Fn zfs.sync.snapshot dataset +Create a snapshot of a filesystem. +Returns 0 if the snapshot was successfully created, +and a nonzero error code otherwise. +.Pp +Note: Taking a snapshot will fail on any pool older than legacy version 27. +To enable taking snapshots from ZCP scripts, the pool must be upgraded. +.Pp +.Bl -tag -compact -width "newbookmark (string)" +.It Ar dataset Pq string +Name of snapshot to create. +.El +.It Fn zfs.sync.rename_snapshot dataset oldsnapname newsnapname +Rename a snapshot of a filesystem or a volume. +Returns 0 if the snapshot was successfully renamed, +and a nonzero error code otherwise. +.Pp +.Bl -tag -compact -width "newbookmark (string)" +.It Ar dataset Pq string +Name of the snapshot's parent dataset. +.It Ar oldsnapname Pq string +Original name of the snapshot. +.It Ar newsnapname Pq string +New name of the snapshot. +.El +.It Fn zfs.sync.bookmark source newbookmark +Create a bookmark of an existing source snapshot or bookmark. +Returns 0 if the new bookmark was successfully created, +and a nonzero error code otherwise. +.Pp +Note: Bookmarking requires the corresponding pool feature to be enabled. +.Pp +.Bl -tag -compact -width "newbookmark (string)" +.It Ar source Pq string +Full name of the existing snapshot or bookmark. +.It Ar newbookmark Pq string +Full name of the new bookmark. +.El +.El +.It Sy zfs.check submodule +For each function in the +.Sy zfs.sync +submodule, there is a corresponding +.Sy zfs.check +function which performs a "dry run" of the same operation. +Each takes the same arguments as its +.Sy zfs.sync +counterpart and returns 0 if the operation would succeed, +or a non-zero error code if it would fail, along with any other error details. +That is, each has the same behavior as the corresponding sync function except +for actually executing the requested change. +For example, +.Fn zfs.check.destroy \&"fs" +returns 0 if +.Fn zfs.sync.destroy \&"fs" +would successfully destroy the dataset. +.Pp +The available +.Sy zfs.check +functions are: +.Bl -tag -compact -width "xx" +.It Fn zfs.check.clone snapshot newdataset +.It Sy zfs.check.destroy Ns Pq Ar dataset , Op Ar defer Ns = Ns Sy true Ns | Ns Sy false +.It Fn zfs.check.promote dataset +.It Fn zfs.check.rollback filesystem +.It Fn zfs.check.set_property dataset property value +.It Fn zfs.check.snapshot dataset +.El +.It Sy zfs.list submodule +The zfs.list submodule provides functions for iterating over datasets and +properties. +Rather than returning tables, these functions act as Lua iterators, and are +generally used as follows: +.Bd -literal -compact -offset indent +.No for child in Fn zfs.list.children \&"rpool" No do + ... +end +.Ed +.Pp +The available +.Sy zfs.list +functions are: +.Bl -tag -width "xx" +.It Fn zfs.list.clones snapshot +Iterate through all clones of the given snapshot. +.Pp +.Bl -tag -compact -width "snapshot (string)" +.It Ar snapshot Pq string +Must be a valid snapshot path in the current pool. +.El +.It Fn zfs.list.snapshots dataset +Iterate through all snapshots of the given dataset. +Each snapshot is returned as a string containing the full dataset name, +e.g. "pool/fs@snap". +.Pp +.Bl -tag -compact -width "snapshot (string)" +.It Ar dataset Pq string +Must be a valid filesystem or volume. +.El +.It Fn zfs.list.children dataset +Iterate through all direct children of the given dataset. +Each child is returned as a string containing the full dataset name, +e.g. "pool/fs/child". +.Pp +.Bl -tag -compact -width "snapshot (string)" +.It Ar dataset Pq string +Must be a valid filesystem or volume. +.El +.It Fn zfs.list.bookmarks dataset +Iterate through all bookmarks of the given dataset. +Each bookmark is returned as a string containing the full dataset name, +e.g. "pool/fs#bookmark". +.Pp +.Bl -tag -compact -width "snapshot (string)" +.It Ar dataset Pq string +Must be a valid filesystem or volume. +.El +.It Fn zfs.list.holds snapshot +Iterate through all user holds on the given snapshot. +Each hold is returned +as a pair of the hold's tag and the timestamp (in seconds since the epoch) at +which it was created. +.Pp +.Bl -tag -compact -width "snapshot (string)" +.It Ar snapshot Pq string +Must be a valid snapshot. +.El +.It Fn zfs.list.properties dataset +An alias for zfs.list.user_properties (see relevant entry). +.Pp +.Bl -tag -compact -width "snapshot (string)" +.It Ar dataset Pq string +Must be a valid filesystem, snapshot, or volume. +.El +.It Fn zfs.list.user_properties dataset +Iterate through all user properties for the given dataset. +For each step of the iteration, output the property name, its value, +and its source. +Throws a Lua error if the dataset is invalid. +.Pp +.Bl -tag -compact -width "snapshot (string)" +.It Ar dataset Pq string +Must be a valid filesystem, snapshot, or volume. +.El +.It Fn zfs.list.system_properties dataset +Returns an array of strings, the names of the valid system (non-user defined) +properties for the given dataset. +Throws a Lua error if the dataset is invalid. +.Pp +.Bl -tag -compact -width "snapshot (string)" +.It Ar dataset Pq string +Must be a valid filesystem, snapshot or volume. +.El +.El +.El +. +.Sh EXAMPLES +. +.Ss Example 1 +The following channel program recursively destroys a filesystem and all its +snapshots and children in a naive manner. +Note that this does not involve any error handling or reporting. +.Bd -literal -offset indent +function destroy_recursive(root) + for child in zfs.list.children(root) do + destroy_recursive(child) + end + for snap in zfs.list.snapshots(root) do + zfs.sync.destroy(snap) + end + zfs.sync.destroy(root) +end +destroy_recursive("pool/somefs") +.Ed +. +.Ss Example 2 +A more verbose and robust version of the same channel program, which +properly detects and reports errors, and also takes the dataset to destroy +as a command line argument, would be as follows: +.Bd -literal -offset indent +succeeded = {} +failed = {} + +function destroy_recursive(root) + for child in zfs.list.children(root) do + destroy_recursive(child) + end + for snap in zfs.list.snapshots(root) do + err = zfs.sync.destroy(snap) + if (err ~= 0) then + failed[snap] = err + else + succeeded[snap] = err + end + end + err = zfs.sync.destroy(root) + if (err ~= 0) then + failed[root] = err + else + succeeded[root] = err + end +end + +args = ... +argv = args["argv"] + +destroy_recursive(argv[1]) + +results = {} +results["succeeded"] = succeeded +results["failed"] = failed +return results +.Ed +. +.Ss Example 3 +The following function performs a forced promote operation by attempting to +promote the given clone and destroying any conflicting snapshots. +.Bd -literal -offset indent +function force_promote(ds) + errno, details = zfs.check.promote(ds) + if (errno == EEXIST) then + assert(details ~= Nil) + for i, snap in ipairs(details) do + zfs.sync.destroy(ds .. "@" .. snap) + end + elseif (errno ~= 0) then + return errno + end + return zfs.sync.promote(ds) +end +.Ed |