Content-type: text/html
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/
The channel program given by script will be run on pool and any attempts to access or modify other pools will cause an error.
All remaining argument strings will be passed directly to the Lua script as described in the Sx LUA INTERFACE section below.
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 "..." syntax 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 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 error. 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'
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 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.
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 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.
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:
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.
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.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 arguments 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}
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:
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 defined 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
dtrace -n 'zfs-dbgmsg{trace(stringof(arg0))}'
msg (string) Debug message to be printed.
dataset (string) Dataset to check for existence. Must be in the target pool.
dataset (string) Filesystem or snapshot path to retrieve properties from.
property (string) Name of property to retrieve. All filesystem, snapshot 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.
The available sync submodule functions are as follows:
dataset (string) Filesystem or snapshot to be destroyed.
[optional] 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.
dataset (string) Clone to be promoted.
filesystem (string) Filesystem to rollback.
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.
The available zfs.check functions are:
for child in zfs.list.children("rpool") do
...
end
The available zfs.list functions are:
snapshot (string) Must be a valid snapshot path in the current pool.
dataset (string) Must be a valid filesystem or volume.
dataset (string) Must be a valid filesystem or volume.
dataset (string) Must be a valid filesystem, snapshot, or volume.
dataset (string) Must be a valid filesystem, snapshot or volume.
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")
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
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