Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
ZFS-PROGRAM(8)		     System Manager's Manual		  ZFS-PROGRAM(8)

NAME
     zfs-program -- execute ZFS channel programs

SYNOPSIS
     zfs program [-jn] [-t instruction-limit] [-m memory-limit] pool script
	 [script arguments]

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 concur-
     rently.  A library of ZFS	calls  is  made  available  to	channel  program
     scripts.  Channel programs may only be run with root privileges.

     A	modified  version of the Lua 5.2 interpreter is used to run channel pro-
     gram   scripts.	 The	Lua    5.2    manual	can    be    found    at
     http://www.lua.org/manual/5.2/

     The  channel  program given by script will be run on pool, and any attempts
     to access or modify other pools will cause an error.

OPTIONS
     -j, --json
	 Display channel program output in JSON format.  When this flag is spec-
	 ified and standard output is empty - channel program encountered an er-
	 ror.  The details of such an error will be printed to standard error in
	 plain text.

     -n  Executes a read-only channel program, which runs faster.   The  program
	 cannot change on-disk state by calling functions from the zfs.sync sub-
	 module.   The program can be used to gather information such as proper-
	 ties 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.

     -t 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	instruc-
	 tions.

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

     All remaining argument strings will be passed directly to the Lua script as
     described in the "LUA INTERFACE" section below.

LUA INTERFACE
     A channel program can be invoked either from the command line, or via a li-
     brary call to lzc_channel_program().

   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':
	   args = ...
	   argv = args["argv"]
	   -- argv == {1="arg1", 2="arg2", ...}

     If  invoked  from	the  libzfs interface, an arbitrary argument list can be
     passed to the channel program, which is accessible via the same "..."  syn-
     tax in Lua:
	   args = ...
	   -- args == {"foo"="bar", "baz"={...}, ...}

     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  arr[0] in a C array passed to a channel program will be stored
     in arr[1] when accessed from Lua.

   Return Values
     Lua return statements take the form:
	   return ret0, ret1, ret2, ...

     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 er-
     ror.  However, tables containing multiple values can still be returned.  If
     invoked from the command line, a return statement:
	   a = {foo="bar", baz=2}
	   return a

     Will be output formatted as:
	   Channel program fully executed with return value:
	       return:
		   baz: 2
		   foo: 'bar'

   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:
	   error: "error string, including Lua stack trace"

     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.

     If the channel program exhausts an instruction or memory limit, a fatal er-
     ror 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 suc-
     cessfully	once, you can guarantee that it will finish successfully against
     a similar size system.

     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.

     Note: ZFS API functions do not generate Fatal  Errors  when  correctly  in-
     voked,  they return an error code and the channel program continues execut-
     ing.  See the "ZFS API" section below for function-specific details on  er-
     ror return codes.

   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 equiva-
     lents, and vice-versa.

     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  con-
     verted  to  an nvlist, with table values converted to their natural equiva-
     lents:
	   string    ->   string
	   number    ->   int64
	   boolean   ->   boolean_value
	   nil	     ->   boolean (no value)
	   table     ->   nvlist

     Likewise, table keys are replaced by string equivalents as follows:
	   string    ->   no change
	   number    ->   signed decimal string ("%lld")
	   boolean   ->   "true" | "false"

     Any collision of table key strings (for example, the string  "true"  and  a
     true boolean value) will cause a fatal error.

     Lua numbers are represented internally as signed 64-bit integers.

LUA STANDARD LIBRARY
     The following Lua built-in base library functions are available:
	   assert   rawlen	   collectgarbage   rawget
	   error    rawset	   getmetatable     select
	   ipairs   setmetatable   next 	    tonumber
	   pairs    tostring	   rawequal	    type

     All  functions  in the coroutine, string, and table built-in submodules are
     also available.  A complete list and  documentation  of  these  modules  is
     available in the Lua manual.

     The  following  functions base library functions have been disabled and are
     not available for use in channel programs:
	   dofile   loadfile   load   pcall   print   xpcall

ZFS API
   Function Arguments
     Each API function takes a fixed set of required  positional  arguments  and
     optional keyword arguments.  For example, the destroy function takes a sin-
     gle  positional string argument (the name of the dataset to destroy) and an
     optional "defer" keyword boolean argument.  When using parentheses to spec-
     ify the arguments to a Lua function, only positional arguments can be used:
	   zfs.sync.destroy("rpool@snap")

     To use keyword arguments, functions must be called with a	single	argument
     that is a Lua table containing entries mapping integers to positional argu-
     ments and strings to keyword arguments:
	   zfs.sync.destroy({1="rpool@snap", defer=true})

     The  Lua language allows curly braces to be used in place of parenthesis as
     syntactic sugar for this calling convention:
	   zfs.sync.snapshot{"rpool@snap", defer=true}

   Function Return Values
     If an API function succeeds, it returns 0.  If it fails, it returns an  er-
     ror 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.

     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  er-
     ror  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:
	   errno = zfs.sync.promote(dataset)

     Or, the error details can be retrieved:
	   errno, details = zfs.sync.promote(dataset)
	   if (errno == EEXIST) then
	       assert(details ~= Nil)
	       list_of_conflicting_snapshots = details
	   end

     The  following  global  aliases for API function error return codes are de-
     fined for use in channel programs:
	   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

   API Functions
     For detailed descriptions of the exact behavior of any  ZFS  administrative
     operations, see the main zfs(8) manual page.

     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
	       dtrace -n 'zfs-dbgmsg{trace(stringof(arg0))}'

	 msg (string)	    Debug message to be printed.

     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,
	 zfs.exists("rpool/nonexistent_fs")	  returns	false,	     but
	 zfs.exists("somepool/fs_that_may_exist") will error.

	 dataset (string)   Dataset to check for existence.  Must be in the tar-
			    get pool.

     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 nega-
	 tive.

	 dataset (string)   Filesystem or snapshot path to  retrieve  properties
			    from.
	 property (string)  Name of property to retrieve.  All filesystem, snap-
			    shot  and volume properties are supported except for
			    mounted  and  iscsioptions.    Also   supports   the
			    written@snap and written#bookmark properties and the
			    <user|group><quota|used>@id  properties,  though the
			    id must be in numeric form.

     zfs.sync submodule
	 The sync submodule contains functions that modify  the  on-disk  state.
	 They are executed in "syncing context".

	 The available sync submodule functions are as follows:

	 zfs.sync.clone(snapshot, newdataset)
	     Create a new filesystem from a snapshot.  Returns 0 if the filesys-
	     tem was successfully created, and a nonzero error code otherwise.

	     Note:  Due to general limitations in channel programs, a filesystem
	     created this way will not be mounted, regardless of  the  value  of
	     the mountpoint and canmount properties.  This limitation may be re-
	     moved   in   the	future,  so  it  is  recommended  that	you  set
	     mountpoint=none or canmount=off or noauto to avoid surprises.

	     snapshot (string)	   Name of the source snapshot to clone.
	     newdataset (string)   Name of the target dataset to create.

	 zfs.sync.destroy(dataset, [defer=true|false])
	     Destroy the given dataset.  Returns 0 on successful destroy,  or  a
	     nonzero error code if the dataset could not be destroyed (for exam-
	     ple, if the dataset has any active children or clones).

	     dataset (string)	   Filesystem or snapshot to be destroyed.
	     [defer (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.

	 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 an-
	     cestor property is set.  The zfs inherit -S option has not been im-
	     plemented.   Returns  0  on success, or a nonzero error code if the
	     property could not be cleared.

	     dataset (string)	   Filesystem or snapshot containing  the  prop-
				   erty to clear.
	     property (string)	   The	property  to  clear.  Allowed properties
				   are the same as those  for  the  zfs  inherit
				   command.

	 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  re-
	     turned,  the  second  return  value will be an array of the clone's
	     snapshots whose names collide with snapshots of the parent filesys-
	     tem.

	     dataset (string)	   Clone to be promoted.

	 zfs.sync.rollback(filesystem)
	     Rollback to the previous snapshot for a dataset.  Returns 0 on suc-
	     cessful 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 filesys-
	     tem is mounted.

	     filesystem (string)   Filesystem to rollback.

	 zfs.sync.set_prop(dataset, property, value)
	     Sets  the given property on a dataset.  Currently only user proper-
	     ties are supported.  Returns 0  if  the  property	was  set,  or  a
	     nonzero error code otherwise.

	     dataset (string)	   The dataset where the property will be set.
	     property (string)	   The property to set.
	     value (string)	   The value of the property to be set.

	 zfs.sync.snapshot(dataset)
	     Create  a	snapshot of a filesystem.  Returns 0 if the snapshot was
	     successfully created, and a nonzero error code otherwise.

	     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.

	     dataset (string)	   Name of snapshot to create.

	 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 other-
	     wise.

	     dataset (string)	   Name of the snapshot's parent dataset.
	     oldsnapname (string)  Original name of the snapshot.
	     newsnapname (string)  New name of the snapshot.

	 zfs.sync.bookmark(source, newbookmark)
	     Create a bookmark of an existing source snapshot or bookmark.   Re-
	     turns 0 if the new bookmark was successfully created, and a nonzero
	     error code otherwise.

	     Note: Bookmarking requires the corresponding pool feature to be en-
	     abled.

	     source (string)	   Full  name  of the existing snapshot or book-
				   mark.
	     newbookmark (string)  Full name of the new bookmark.

     zfs.check submodule
	 For each function in the zfs.sync submodule, there is	a  corresponding
	 zfs.check  function  which  performs a "dry run" of the same operation.
	 Each takes the same arguments as its 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 execut-
	 ing the requested change.  For example, zfs.check.destroy("fs") returns
	 0 if zfs.sync.destroy("fs") would successfully destroy the dataset.

	 The available zfs.check functions are:
	 zfs.check.clone(snapshot, newdataset)
	 zfs.check.destroy(dataset, [defer=true|false])
	 zfs.check.promote(dataset)
	 zfs.check.rollback(filesystem)
	 zfs.check.set_property(dataset, property, value)
	 zfs.check.snapshot(dataset)

     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:
	       for child in zfs.list.children("rpool") do
		   ...
	       end

	 The available zfs.list functions are:

	 zfs.list.clones(snapshot)
	     Iterate through all clones of the given snapshot.

	     snapshot (string)	Must be a valid snapshot  path	in  the  current
				pool.

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

	     dataset (string)	Must be a valid filesystem or volume.

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

	     dataset (string)	Must be a valid filesystem or volume.

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

	     dataset (string)	Must be a valid filesystem or volume.

	 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.

	     snapshot (string)	Must be a valid snapshot.

	 zfs.list.properties(dataset)
	     An alias for zfs.list.user_properties (see relevant entry).

	     dataset (string)	Must be a valid filesystem, snapshot, or volume.

	 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.

	     dataset (string)	Must be a valid filesystem, snapshot, or volume.

	 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.

	     dataset (string)	Must be a valid filesystem, snapshot or volume.

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

	   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")

   Example 2
     A more verbose and robust version of the same channel program, which  prop-
     erly detects and reports errors, and also takes the dataset to destroy as a
     command line argument, would be as follows:

	   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

   Example 3
     The following function performs a forced promote operation by attempting to
     promote the given clone and destroying any conflicting snapshots.

	   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

FreeBSD ports 15.quarterly	  June 5, 2025			  ZFS-PROGRAM(8)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=zfs-program&sektion=8&manpath=FreeBSD+Ports+15.1.quarterly>

home | help